Annotation of src/sys/arch/amiga/amiga/machdep.c, Revision 1.199
1.198 yamt 1: /* $NetBSD$ */
1.40 cgd 2:
1.1 mw 3: /*
4: * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * the Systems Programming Group of the University of Utah Computer
9: * Science Department.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
1.185 agc 19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: * from: Utah $Hdr: machdep.c 1.63 91/04/24$
36: *
37: * @(#)machdep.c 7.16 (Berkeley) 6/3/91
38: */
39:
40: /*
41: * Copyright (c) 1988 University of Utah.
42: *
43: * This code is derived from software contributed to Berkeley by
44: * the Systems Programming Group of the University of Utah Computer
45: * Science Department.
46: *
47: * Redistribution and use in source and binary forms, with or without
48: * modification, are permitted provided that the following conditions
49: * are met:
50: * 1. Redistributions of source code must retain the above copyright
51: * notice, this list of conditions and the following disclaimer.
52: * 2. Redistributions in binary form must reproduce the above copyright
53: * notice, this list of conditions and the following disclaimer in the
54: * documentation and/or other materials provided with the distribution.
1.1 mw 55: * 3. All advertising materials mentioning features or use of this software
56: * must display the following acknowledgement:
57: * This product includes software developed by the University of
58: * California, Berkeley and its contributors.
59: * 4. Neither the name of the University nor the names of its contributors
60: * may be used to endorse or promote products derived from this software
61: * without specific prior written permission.
62: *
63: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73: * SUCH DAMAGE.
74: *
1.4 mw 75: * from: Utah $Hdr: machdep.c 1.63 91/04/24$
76: *
77: * @(#)machdep.c 7.16 (Berkeley) 6/3/91
1.1 mw 78: */
1.116 jonathan 79:
80: #include "opt_ddb.h"
1.120 jonathan 81: #include "opt_compat_netbsd.h"
1.182 martin 82: #include "opt_fpu_emulate.h"
83: #include "opt_lev6_defer.h"
84: #include "opt_m060sp.h"
85: #include "opt_panicbutton.h"
1.167 aymeric 86:
87: #include <sys/cdefs.h>
1.198 yamt 88: __KERNEL_RCSID(0, "$NetBSD$");
1.1 mw 89:
1.9 chopps 90: #include <sys/param.h>
91: #include <sys/systm.h>
1.148 thorpej 92: #include <sys/callout.h>
1.9 chopps 93: #include <sys/signalvar.h>
94: #include <sys/kernel.h>
95: #include <sys/proc.h>
96: #include <sys/buf.h>
97: #include <sys/reboot.h>
98: #include <sys/conf.h>
99: #include <sys/file.h>
100: #include <sys/malloc.h>
101: #include <sys/mbuf.h>
102: #include <sys/msgbuf.h>
1.5 mw 103: #include <sys/user.h>
1.23 chopps 104: #include <sys/vnode.h>
1.124 veego 105: #include <sys/device.h>
1.23 chopps 106: #include <sys/queue.h>
1.39 cgd 107: #include <sys/mount.h>
1.68 mhitch 108: #include <sys/core.h>
109: #include <sys/kcore.h>
1.181 ragge 110: #include <sys/ksyms.h>
1.155 cgd 111:
1.170 is 112: #include <sys/exec.h>
113:
1.159 is 114: #if defined(DDB) && defined(__ELF__)
115: #include <sys/exec_elf.h>
116: #endif
1.170 is 117:
118: #include <sys/exec_aout.h>
1.159 is 119:
1.9 chopps 120: #include <net/netisr.h>
1.155 cgd 121: #undef PS /* XXX netccitt/pk.h conflict with machine/reg.h? */
1.154 mrg 122:
1.143 ragge 123: #define MAXMEM 64*1024 /* XXX - from cmap.h */
1.121 mhitch 124: #include <uvm/uvm_extern.h>
125:
1.103 is 126: #include <sys/sysctl.h>
1.61 veego 127:
128: #include <machine/db_machdep.h>
129: #include <ddb/db_sym.h>
130: #include <ddb/db_extern.h>
131:
1.23 chopps 132: #include <machine/cpu.h>
133: #include <machine/reg.h>
134: #include <machine/psl.h>
135: #include <machine/pte.h>
1.68 mhitch 136: #include <machine/kcore.h>
1.23 chopps 137: #include <dev/cons.h>
138: #include <amiga/amiga/isr.h>
1.9 chopps 139: #include <amiga/amiga/custom.h>
1.66 is 140: #ifdef DRACO
141: #include <amiga/amiga/drcustom.h>
1.122 is 142: #include <m68k/include/asm_single.h>
1.66 is 143: #endif
1.9 chopps 144: #include <amiga/amiga/cia.h>
145: #include <amiga/amiga/cc.h>
146: #include <amiga/amiga/memlist.h>
1.45 chopps 147:
1.17 chopps 148: #include "fd.h"
1.22 chopps 149: #include "ser.h"
1.181 ragge 150: #include "ksyms.h"
1.1 mw 151:
1.61 veego 152: /* prototypes */
1.166 aymeric 153: void identifycpu(void);
154: vm_offset_t reserve_dumppages(vm_offset_t);
155: void dumpsys(void);
156: void initcpu(void);
157: void straytrap(int, u_short);
158: static void netintr(void);
159: static void call_sicallbacks(void);
160: static void _softintr_callit(void *, void *);
161: void intrhand(int);
1.64 mhitch 162: #if NSER > 0
1.166 aymeric 163: void ser_outintr(void);
1.64 mhitch 164: #endif
165: #if NFD > 0
1.166 aymeric 166: void fdintr(int);
1.64 mhitch 167: #endif
1.165 aymeric 168:
169: volatile unsigned int interrupt_depth = 0;
1.61 veego 170:
1.1 mw 171: /*
1.111 is 172: * patched by some devices at attach time (currently, only the coms)
1.81 is 173: */
1.111 is 174: u_int16_t amiga_serialspl = PSL_S|PSL_IPL4;
1.81 is 175:
1.166 aymeric 176: struct vm_map *exec_map = NULL;
1.163 chs 177: struct vm_map *mb_map = NULL;
178: struct vm_map *phys_map = NULL;
1.121 mhitch 179:
1.100 leo 180: caddr_t msgbufaddr;
1.141 is 181: paddr_t msgbufpa;
1.100 leo 182:
1.171 aymeric 183: int machineid;
1.1 mw 184: int maxmem; /* max memory per process */
185: int physmem = MAXMEM; /* max supported memory, changes to actual */
186: /*
1.166 aymeric 187: * extender "register" for software interrupts. Moved here
1.45 chopps 188: * from locore.s, since softints are no longer dealt with
189: * in locore.s.
190: */
191: unsigned char ssir;
192: /*
1.1 mw 193: * safepri is a safe priority for sleep to set for a spin-wait
194: * during autoconfiguration or after a panic.
195: */
196: int safepri = PSL_LOWIPL;
197: extern int freebufspace;
198: extern u_int lowram;
199:
200: /* used in init_main.c */
1.192 jandberg 201: const char *cpu_type = "m68k";
1.23 chopps 202: /* the following is used externally (sysctl_hw) */
1.91 veego 203: char machine[] = MACHINE; /* from <machine/param.h> */
1.151 thorpej 204:
205: /* Our exported CPU info; we can have only one. */
206: struct cpu_info cpu_info_store;
1.166 aymeric 207:
1.102 mhitch 208: /*
209: * current open serial device speed; used by some SCSI drivers to reduce
210: * DMA transfer lengths.
211: */
212: int ser_open_speed;
1.172 matt 213:
214: #ifdef DRACO
215: vaddr_t DRCCADDR;
216:
217: volatile u_int8_t *draco_intena, *draco_intpen, *draco_intfrc;
218: volatile u_int8_t *draco_misc;
219: volatile struct drioct *draco_ioct;
220: #endif
1.102 mhitch 221:
1.5 mw 222: /*
1.1 mw 223: * Console initialization: called early on from main,
224: * before vm init or startup. Do enough configuration
225: * to choose and initialize a console.
226: */
227: void
228: consinit()
229: {
1.5 mw 230: /* initialize custom chip interface */
1.66 is 231: #ifdef DRACO
232: if (is_draco()) {
233: /* XXX to be done */
234: } else
235: #endif
236: custom_chips_init();
1.1 mw 237: /*
238: * Initialize the console before we print anything out.
239: */
240: cninit();
1.11 chopps 241:
1.181 ragge 242: #if NKSYMS || defined(DDB) || defined(LKM)
1.114 tv 243: {
1.115 mhitch 244: extern int end[];
1.114 tv 245: extern int *esym;
246:
1.181 ragge 247: ksyms_init((int)esym - (int)&end - sizeof(Elf32_Ehdr),
1.159 is 248: (void *)&end, esym);
1.181 ragge 249: }
1.159 is 250: #endif
1.181 ragge 251: #ifdef DDB
1.11 chopps 252: if (boothowto & RB_KDB)
253: Debugger();
254: #endif
1.1 mw 255: }
256:
257: /*
258: * cpu_startup: allocate memory for variable-sized tables,
1.189 wiz 259: * initialize CPU, and do autoconfiguration.
1.1 mw 260: */
261: void
262: cpu_startup()
263: {
1.136 lukem 264: char pbuf[9];
1.188 pk 265: u_int i;
1.1 mw 266: #ifdef DEBUG
267: extern int pmapdebug;
268: int opmapdebug = pmapdebug;
269: #endif
1.188 pk 270: vaddr_t minaddr, maxaddr;
1.1 mw 271:
1.179 thorpej 272: if (fputype != FPU_NONE)
273: m68k_make_fpu_idle_frame();
274:
1.1 mw 275: /*
276: * Initialize error message buffer (at end of core).
277: */
278: #ifdef DEBUG
279: pmapdebug = 0;
280: #endif
1.111 is 281: /*
282: * pmap_bootstrap has positioned this at the end of kernel
283: * memory segment - map and initialize it now.
284: */
285:
1.100 leo 286: for (i = 0; i < btoc(MSGBUFSIZE); i++)
1.180 thorpej 287: pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE,
288: msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE,
1.142 thorpej 289: VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
1.164 chris 290: pmap_update(pmap_kernel());
1.100 leo 291: initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
1.1 mw 292:
293: /*
294: * Good {morning,afternoon,evening,night}.
295: */
1.191 lukem 296: printf("%s%s", copyright, version);
1.1 mw 297: identifycpu();
1.136 lukem 298: format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
299: printf("total memory = %s\n", pbuf);
1.5 mw 300:
1.121 mhitch 301:
1.188 pk 302: minaddr = 0;
1.1 mw 303:
304: /*
305: * Allocate a submap for exec arguments. This map effectively
306: * limits the number of processes exec'ing at any time.
307: */
1.121 mhitch 308: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.137 thorpej 309: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.1 mw 310:
311: /*
312: * Allocate a submap for physio
313: */
1.121 mhitch 314: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.137 thorpej 315: VM_PHYS_SIZE, 0, FALSE, NULL);
1.1 mw 316:
317: /*
1.86 thorpej 318: * Finally, allocate mbuf cluster submap.
1.1 mw 319: */
1.129 thorpej 320: mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.137 thorpej 321: nmbclusters * mclbytes, VM_MAP_INTRSAFE,
322: FALSE, NULL);
1.1 mw 323:
324: #ifdef DEBUG
325: pmapdebug = opmapdebug;
326: #endif
1.136 lukem 327: format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
328: printf("avail memory = %s\n", pbuf);
1.166 aymeric 329:
1.29 chopps 330: /*
331: * display memory configuration passed from loadbsd
332: */
333: if (memlist->m_nseg > 0 && memlist->m_nseg < 16)
334: for (i = 0; i < memlist->m_nseg; i++)
1.139 is 335: printf("memory segment %d at %08x size %08x\n", i,
1.166 aymeric 336: memlist->m_seg[i].ms_start,
1.29 chopps 337: memlist->m_seg[i].ms_size);
1.66 is 338:
1.78 thorpej 339: #ifdef DEBUG_KERNEL_START
1.80 christos 340: printf("calling initcpu...\n");
1.66 is 341: #endif
1.1 mw 342: /*
343: * Set up CPU-specific registers, cache, etc.
344: */
345: initcpu();
346:
1.73 is 347: #ifdef DEBUG_KERNEL_START
1.80 christos 348: printf("survived initcpu...\n");
1.66 is 349: #endif
1.1 mw 350: }
351:
352: /*
353: * Set registers on exec.
354: */
355: void
1.179 thorpej 356: setregs(l, pack, stack)
357: struct lwp *l;
1.48 christos 358: struct exec_package *pack;
1.1 mw 359: u_long stack;
360: {
1.179 thorpej 361: struct frame *frame = (struct frame *)l->l_md.md_regs;
1.166 aymeric 362:
1.99 mycroft 363: frame->f_sr = PSL_USERSET;
1.48 christos 364: frame->f_pc = pack->ep_entry & ~1;
1.97 mycroft 365: frame->f_regs[D0] = 0;
366: frame->f_regs[D1] = 0;
367: frame->f_regs[D2] = 0;
368: frame->f_regs[D3] = 0;
369: frame->f_regs[D4] = 0;
370: frame->f_regs[D5] = 0;
371: frame->f_regs[D6] = 0;
372: frame->f_regs[D7] = 0;
373: frame->f_regs[A0] = 0;
374: frame->f_regs[A1] = 0;
1.179 thorpej 375: frame->f_regs[A2] = (int)l->l_proc->p_psstr;
1.97 mycroft 376: frame->f_regs[A3] = 0;
377: frame->f_regs[A4] = 0;
378: frame->f_regs[A5] = 0;
379: frame->f_regs[A6] = 0;
1.27 chopps 380: frame->f_regs[SP] = stack;
381:
1.1 mw 382: /* restore a null state frame */
1.179 thorpej 383: l->l_addr->u_pcb.pcb_fpregs.fpf_null = 0;
1.94 is 384: #ifdef FPU_EMULATE
385: if (!fputype)
1.179 thorpej 386: bzero(&l->l_addr->u_pcb.pcb_fpregs, sizeof(struct fpframe));
1.94 is 387: else
388: #endif
1.179 thorpej 389: m68881_restore(&l->l_addr->u_pcb.pcb_fpregs);
1.1 mw 390: }
391:
1.23 chopps 392: /*
393: * Info for CTL_HW
394: */
395: char cpu_model[120];
1.81 is 396:
397: #if defined(M68060)
398: int m68060_pcr_init = 0x21; /* make this patchable */
399: #endif
400:
1.166 aymeric 401:
1.61 veego 402: void
1.1 mw 403: identifycpu()
404: {
1.3 mw 405: /* there's alot of XXX in here... */
1.192 jandberg 406: const char *mach, *mmu, *fpu;
1.3 mw 407:
1.70 is 408: #ifdef M68060
409: char cpubuf[16];
410: u_int32_t pcr;
411: #endif
1.72 is 412:
1.66 is 413: #ifdef DRACO
414: char machbuf[16];
415:
416: if (is_draco()) {
1.80 christos 417: sprintf(machbuf, "DraCo rev.%d", is_draco());
1.66 is 418: mach = machbuf;
1.166 aymeric 419: } else
1.66 is 420: #endif
1.23 chopps 421: if (is_a4000())
422: mach = "Amiga 4000";
423: else if (is_a3000())
424: mach = "Amiga 3000";
1.33 chopps 425: else if (is_a1200())
426: mach = "Amiga 1200";
1.3 mw 427: else
1.23 chopps 428: mach = "Amiga 500/2000";
1.1 mw 429:
1.31 chopps 430: fpu = NULL;
1.72 is 431: #ifdef M68060
1.66 is 432: if (machineid & AMIGA_68060) {
1.195 perry 433: __asm(".word 0x4e7a,0x0808; movl %%d0,%0" : "=d"(pcr) : : "d0");
1.80 christos 434: sprintf(cpubuf, "68%s060 rev.%d",
1.70 is 435: pcr & 0x10000 ? "LC/EC" : "", (pcr>>8)&0xff);
436: cpu_type = cpubuf;
1.66 is 437: mmu = "/MMU";
1.94 is 438: if (pcr & 2) {
439: fpu = "/FPU disabled";
440: fputype = FPU_NONE;
441: } else if (m68060_pcr_init & 2){
442: fpu = "/FPU will be disabled";
443: fputype = FPU_NONE;
444: } else if (machineid & AMIGA_FPU40) {
445: fpu = "/FPU";
446: fputype = FPU_68040; /* XXX */
447: }
1.166 aymeric 448: } else
1.72 is 449: #endif
450: if (machineid & AMIGA_68040) {
1.5 mw 451: cpu_type = "m68040";
1.23 chopps 452: mmu = "/MMU";
1.24 chopps 453: fpu = "/FPU";
1.81 is 454: fputype = FPU_68040; /* XXX */
1.24 chopps 455: } else if (machineid & AMIGA_68030) {
1.23 chopps 456: cpu_type = "m68030"; /* XXX */
457: mmu = "/MMU";
458: } else {
459: cpu_type = "m68020";
460: mmu = " m68851 MMU";
461: }
1.31 chopps 462: if (fpu == NULL) {
1.52 chopps 463: if (machineid & AMIGA_68882) {
1.24 chopps 464: fpu = " m68882 FPU";
1.52 chopps 465: fputype = FPU_68882;
466: } else if (machineid & AMIGA_68881) {
1.24 chopps 467: fpu = " m68881 FPU";
1.52 chopps 468: fputype = FPU_68881;
469: } else {
1.24 chopps 470: fpu = " no FPU";
1.52 chopps 471: fputype = FPU_NONE;
472: }
1.24 chopps 473: }
1.80 christos 474: sprintf(cpu_model, "%s (%s CPU%s%s)", mach, cpu_type, mmu, fpu);
475: printf("%s\n", cpu_model);
1.23 chopps 476: }
1.5 mw 477:
1.23 chopps 478: /*
479: * machine dependent system variables.
480: */
1.187 atatat 481: SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
1.23 chopps 482: {
1.1 mw 483:
1.190 atatat 484: sysctl_createv(clog, 0, NULL, NULL,
485: CTLFLAG_PERMANENT,
1.187 atatat 486: CTLTYPE_NODE, "machdep", NULL,
487: NULL, 0, NULL, 0,
488: CTL_MACHDEP, CTL_EOL);
489:
1.190 atatat 490: sysctl_createv(clog, 0, NULL, NULL,
491: CTLFLAG_PERMANENT,
1.187 atatat 492: CTLTYPE_STRUCT, "console_device", NULL,
493: sysctl_consdev, 0, NULL, sizeof(dev_t),
494: CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
1.1 mw 495: }
1.4 mw 496:
1.3 mw 497: static int waittime = -1;
1.1 mw 498:
1.3 mw 499: void
500: bootsync(void)
1.1 mw 501: {
1.21 chopps 502: if (waittime < 0) {
1.1 mw 503: waittime = 0;
1.121 mhitch 504: vfs_shutdown();
1.1 mw 505: /*
506: * If we've been adjusting the clock, the todr
507: * will be out of synch; adjust it now.
508: */
509: resettodr();
510: }
1.3 mw 511: }
512:
1.63 veego 513:
1.27 chopps 514: void
1.85 gwr 515: cpu_reboot(howto, bootstr)
1.3 mw 516: register int howto;
1.76 mrg 517: char *bootstr;
1.3 mw 518: {
519: /* take a snap shot before clobbering any registers */
1.179 thorpej 520: if (curlwp)
521: savectx(&curlwp->l_addr->u_pcb);
1.3 mw 522:
523: boothowto = howto;
1.61 veego 524: if ((howto & RB_NOSYNC) == 0)
1.3 mw 525: bootsync();
1.63 veego 526:
527: /* Disable interrupts. */
528: spl7();
529:
530: /* If rebooting and a dump is requested do it. */
531: if (howto & RB_DUMP)
532: dumpsys();
533:
1.61 veego 534: if (howto & RB_HALT) {
1.101 veego 535: printf("\n");
536: printf("The operating system has halted.\n");
537: printf("Please press any key to reboot.\n\n");
538: cngetc();
1.1 mw 539: }
1.63 veego 540:
1.101 veego 541: printf("rebooting...\n");
542: DELAY(1000000);
1.63 veego 543: doboot();
1.1 mw 544: /*NOTREACHED*/
545: }
1.63 veego 546:
1.1 mw 547:
1.168 tsutsui 548: u_int32_t dumpmag = 0x8fca0101; /* magic number for savecore */
1.1 mw 549: int dumpsize = 0; /* also for savecore */
550: long dumplo = 0;
1.68 mhitch 551: cpu_kcore_hdr_t cpu_kcore_hdr;
1.1 mw 552:
1.193 chs 553: #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
554: #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
555:
1.61 veego 556: void
1.85 gwr 557: cpu_dumpconf()
1.1 mw 558: {
1.89 thorpej 559: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
560: struct m68k_kcore_hdr *m = &h->un._m68k;
1.174 gehenna 561: const struct bdevsw *bdev;
1.1 mw 562: int nblks;
1.68 mhitch 563: int i;
564: extern u_int Sysseg_pa;
1.115 mhitch 565: extern int end[];
1.89 thorpej 566:
567: bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr));
568:
569: /*
570: * Intitialize the `dispatcher' portion of the header.
571: */
572: strcpy(h->name, machine);
1.180 thorpej 573: h->page_size = PAGE_SIZE;
1.89 thorpej 574: h->kernbase = KERNBASE;
575:
576: /*
577: * Fill in information about our MMU configuration.
578: */
579: m->mmutype = mmutype;
580: m->sg_v = SG_V;
581: m->sg_frame = SG_FRAME;
582: m->sg_ishift = SG_ISHIFT;
583: m->sg_pmask = SG_PMASK;
584: m->sg40_shift1 = SG4_SHIFT1;
585: m->sg40_mask2 = SG4_MASK2;
586: m->sg40_shift2 = SG4_SHIFT2;
587: m->sg40_mask3 = SG4_MASK3;
588: m->sg40_shift3 = SG4_SHIFT3;
589: m->sg40_addr1 = SG4_ADDR1;
590: m->sg40_addr2 = SG4_ADDR2;
591: m->pg_v = PG_V;
592: m->pg_frame = PG_FRAME;
593:
594: /*
595: * Initialize the pointer to the kernel segment table.
596: */
597: m->sysseg_pa = Sysseg_pa;
598:
599: /*
600: * Initialize relocation value such that:
601: *
602: * pa = (va - KERNBASE) + reloc
603: */
604: m->reloc = lowram;
605:
606: /*
607: * Define the end of the relocatable range.
608: */
1.115 mhitch 609: m->relocend = (u_int32_t)&end;
1.1 mw 610:
1.68 mhitch 611: /* XXX new corefile format, single segment + chipmem */
1.1 mw 612: dumpsize = physmem;
1.89 thorpej 613: m->ram_segs[0].start = lowram;
614: m->ram_segs[0].size = ctob(physmem);
1.68 mhitch 615: for (i = 0; i < memlist->m_nseg; i++) {
616: if ((memlist->m_seg[i].ms_attrib & MEMF_CHIP) == 0)
617: continue;
618: dumpsize += btoc(memlist->m_seg[i].ms_size);
1.89 thorpej 619: m->ram_segs[1].start = 0;
620: m->ram_segs[1].size = memlist->m_seg[i].ms_size;
1.68 mhitch 621: break;
622: }
1.199 ! yamt 623: if ((bdev = bdevsw_lookup(dumpdev)) == NULL) {
1.197 mrg 624: dumpdev = NODEV;
625: return;
626: }
627: if (bdev->d_psize != NULL) {
1.174 gehenna 628: nblks = (*bdev->d_psize)(dumpdev);
1.1 mw 629: if (dumpsize > btoc(dbtob(nblks - dumplo)))
630: dumpsize = btoc(dbtob(nblks - dumplo));
631: else if (dumplo == 0)
1.68 mhitch 632: dumplo = nblks - btodb(ctob(dumpsize));
1.1 mw 633: }
1.68 mhitch 634: --dumplo; /* XXX assume header fits in one block */
1.1 mw 635: /*
1.180 thorpej 636: * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
1.1 mw 637: * in case the dump device includes a disk label.
638: */
1.180 thorpej 639: if (dumplo < btodb(PAGE_SIZE))
640: dumplo = btodb(PAGE_SIZE);
1.1 mw 641: }
642:
643: /*
644: * Doadump comes here after turning off memory management and
645: * getting on the dump stack, either when called above, or by
646: * the auto-restart code.
647: */
1.57 chopps 648: #define BYTES_PER_DUMP MAXPHYS /* Must be a multiple of pagesize XXX small */
1.55 chopps 649: static vm_offset_t dumpspace;
650:
651: vm_offset_t
652: reserve_dumppages(p)
653: vm_offset_t p;
654: {
655: dumpspace = p;
656: return (p + BYTES_PER_DUMP);
657: }
658:
1.61 veego 659: void
1.1 mw 660: dumpsys()
661: {
1.68 mhitch 662: unsigned bytes, i, n, seg;
1.55 chopps 663: int maddr, psize;
664: daddr_t blkno;
1.166 aymeric 665: int (*dump)(dev_t, daddr_t, caddr_t, size_t);
1.55 chopps 666: int error = 0;
1.68 mhitch 667: kcore_seg_t *kseg_p;
668: cpu_kcore_hdr_t *chdr_p;
1.193 chs 669: char dump_hdr[MDHDRSIZE];
1.174 gehenna 670: const struct bdevsw *bdev;
1.1 mw 671:
672: if (dumpdev == NODEV)
673: return;
1.174 gehenna 674: bdev = bdevsw_lookup(dumpdev);
675: if (bdev == NULL || bdev->d_psize == NULL)
676: return;
1.1 mw 677: /*
678: * For dumps during autoconfiguration,
679: * if dump device has already configured...
680: */
681: if (dumpsize == 0)
1.85 gwr 682: cpu_dumpconf();
1.108 mycroft 683: if (dumplo <= 0) {
684: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
685: minor(dumpdev));
1.1 mw 686: return;
1.108 mycroft 687: }
688: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
689: minor(dumpdev), dumplo);
1.55 chopps 690:
1.174 gehenna 691: psize = (*bdev->d_psize)(dumpdev);
1.80 christos 692: printf("dump ");
1.55 chopps 693: if (psize == -1) {
1.80 christos 694: printf("area unavailable.\n");
1.55 chopps 695: return;
696: }
1.68 mhitch 697: kseg_p = (kcore_seg_t *)dump_hdr;
698: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
699: bzero(dump_hdr, sizeof(dump_hdr));
700:
701: /*
702: * Generate a segment header
703: */
704: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
1.193 chs 705: kseg_p->c_size = MDHDRSIZE - ALIGN(sizeof(*kseg_p));
1.68 mhitch 706:
707: /*
708: * Add the md header
709: */
710:
711: *chdr_p = cpu_kcore_hdr;
712:
1.55 chopps 713: bytes = ctob(dumpsize);
1.89 thorpej 714: maddr = cpu_kcore_hdr.un._m68k.ram_segs[0].start;
1.68 mhitch 715: seg = 0;
1.55 chopps 716: blkno = dumplo;
1.174 gehenna 717: dump = bdev->d_dump;
1.193 chs 718: error = (*dump) (dumpdev, blkno, (caddr_t)dump_hdr, sizeof(dump_hdr));
719: blkno += btodb(sizeof(dump_hdr));
1.68 mhitch 720: for (i = 0; i < bytes && error == 0; i += n) {
1.55 chopps 721: /* Print out how many MBs we have to go. */
722: n = bytes - i;
723: if (n && (n % (1024 * 1024)) == 0)
1.80 christos 724: printf("%d ", n / (1024 * 1024));
1.55 chopps 725:
726: /* Limit size for next transfer. */
727: if (n > BYTES_PER_DUMP)
728: n = BYTES_PER_DUMP;
729:
1.68 mhitch 730: if (maddr == 0) { /* XXX kvtop chokes on this */
1.180 thorpej 731: maddr += PAGE_SIZE;
732: n -= PAGE_SIZE;
733: i += PAGE_SIZE;
1.68 mhitch 734: ++blkno; /* XXX skip physical page 0 */
735: }
1.55 chopps 736: (void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);
737: error = (*dump) (dumpdev, blkno, (caddr_t) dumpspace, n);
738: if (error)
739: break;
740: maddr += n;
741: blkno += btodb(n); /* XXX? */
1.89 thorpej 742: if (maddr >= (cpu_kcore_hdr.un._m68k.ram_segs[seg].start +
743: cpu_kcore_hdr.un._m68k.ram_segs[seg].size)) {
1.68 mhitch 744: ++seg;
1.89 thorpej 745: maddr = cpu_kcore_hdr.un._m68k.ram_segs[seg].start;
746: if (cpu_kcore_hdr.un._m68k.ram_segs[seg].size == 0)
1.68 mhitch 747: break;
748: }
1.55 chopps 749: }
750:
751: switch (error) {
1.1 mw 752:
753: case ENXIO:
1.80 christos 754: printf("device bad\n");
1.1 mw 755: break;
756:
757: case EFAULT:
1.80 christos 758: printf("device not ready\n");
1.1 mw 759: break;
760:
761: case EINVAL:
1.80 christos 762: printf("area improper\n");
1.1 mw 763: break;
764:
765: case EIO:
1.80 christos 766: printf("i/o error\n");
1.1 mw 767: break;
768:
769: default:
1.80 christos 770: printf("succeeded\n");
1.1 mw 771: break;
772: }
1.80 christos 773: printf("\n\n");
1.55 chopps 774: delay(5000000); /* 5 seconds */
1.1 mw 775: }
776:
777: /*
778: * Return the best possible estimate of the time in the timeval
779: * to which tvp points. We do this by returning the current time
780: * plus the amount of time since the last clock interrupt (clock.c:clkread).
781: *
782: * Check that this time is no less than any previously-reported time,
783: * which could happen around the time of a clock adjustment. Just for fun,
784: * we guarantee that the time will be greater than the value obtained by a
785: * previous call.
786: */
1.43 chopps 787: void
1.1 mw 788: microtime(tvp)
789: register struct timeval *tvp;
790: {
1.45 chopps 791: int s = spl7();
1.1 mw 792: static struct timeval lasttime;
793:
794: *tvp = time;
795: tvp->tv_usec += clkread();
1.144 msaitoh 796: while (tvp->tv_usec >= 1000000) {
1.1 mw 797: tvp->tv_sec++;
798: tvp->tv_usec -= 1000000;
799: }
800: if (tvp->tv_sec == lasttime.tv_sec &&
801: tvp->tv_usec <= lasttime.tv_usec &&
1.144 msaitoh 802: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
1.1 mw 803: tvp->tv_sec++;
804: tvp->tv_usec -= 1000000;
805: }
806: lasttime = *tvp;
807: splx(s);
808: }
809:
1.61 veego 810: void
1.1 mw 811: initcpu()
812: {
1.166 aymeric 813: typedef void trapfun(void);
1.93 is 814:
1.67 is 815: /* XXX should init '40 vecs here, too */
1.94 is 816: #if defined(M68060) || defined(M68040) || defined(DRACO) || defined(FPU_EMULATE)
1.93 is 817: extern trapfun *vectab[256];
1.70 is 818: #endif
1.66 is 819:
1.90 is 820: #if defined(M68060) || defined(M68040)
1.93 is 821: extern trapfun addrerr4060;
1.90 is 822: #endif
823:
1.72 is 824: #ifdef M68060
1.93 is 825: extern trapfun buserr60;
1.69 is 826: #if defined(M060SP)
1.82 is 827: /*extern u_int8_t I_CALL_TOP[];*/
1.93 is 828: extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60;
1.66 is 829: extern u_int8_t FP_CALL_TOP[];
1.69 is 830: #else
1.93 is 831: extern trapfun illinst;
1.72 is 832: #endif
1.93 is 833: extern trapfun fpfault;
1.69 is 834: #endif
1.66 is 835:
1.90 is 836: #ifdef M68040
1.93 is 837: extern trapfun buserr40;
1.90 is 838: #endif
839:
1.70 is 840: #ifdef DRACO
1.93 is 841: extern trapfun DraCoIntr, DraCoLev1intr, DraCoLev2intr;
1.77 is 842: u_char dracorev;
1.70 is 843: #endif
844:
1.94 is 845: #ifdef FPU_EMULATE
846: extern trapfun fpemuli;
847: #endif
848:
1.70 is 849: #ifdef M68060
1.66 is 850: if (machineid & AMIGA_68060) {
1.94 is 851: if (machineid & AMIGA_FPU40 && m68060_pcr_init & 2) {
1.166 aymeric 852: /*
1.94 is 853: * in this case, we're about to switch the FPU off;
854: * do a FNOP to avoid stray FP traps later
855: */
856: __asm("fnop");
857: /* ... and mark FPU as absent for identifyfpu() */
858: machineid &= ~(AMIGA_FPU40|AMIGA_68882|AMIGA_68881);
859: }
1.195 perry 860: __asm volatile ("movl %0,%%d0; .word 0x4e7b,0x0808" : :
1.66 is 861: "d"(m68060_pcr_init):"d0" );
1.90 is 862:
863: /* bus/addrerr vectors */
1.93 is 864: vectab[2] = buserr60;
865: vectab[3] = addrerr4060;
1.66 is 866: #if defined(M060SP)
867:
868: /* integer support */
1.93 is 869: vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/;
1.66 is 870:
871: /* floating point support */
1.81 is 872: /*
873: * XXX maybe we really should run-time check for the
874: * stack frame format here:
875: */
1.93 is 876: vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/;
1.81 is 877:
1.93 is 878: vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/;
879: vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/;
1.66 is 880:
1.93 is 881: vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00];
882: vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08];
883: vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10];
884: vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18];
885: vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20];
886: vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28];
1.66 is 887:
888: #else
1.93 is 889: vectab[61] = illinst;
1.66 is 890: #endif
1.93 is 891: vectab[48] = fpfault;
1.66 is 892: }
893: #endif
1.70 is 894:
1.81 is 895: /*
1.166 aymeric 896: * Vector initialization for special motherboards
1.81 is 897: */
1.90 is 898: #ifdef M68040
899: #ifdef M68060
900: else
901: #endif
902: if (machineid & AMIGA_68040) {
903: /* addrerr vector */
1.93 is 904: vectab[2] = buserr40;
905: vectab[3] = addrerr4060;
1.90 is 906: }
907: #endif
1.94 is 908:
909: #ifdef FPU_EMULATE
910: if (!(machineid & (AMIGA_68881|AMIGA_68882|AMIGA_FPU40))) {
911: vectab[11] = fpemuli;
912: printf("FPU software emulation initialized.\n");
913: }
914: #endif
915:
916: /*
1.166 aymeric 917: * Vector initialization for special motherboards
1.94 is 918: */
1.81 is 919:
1.70 is 920: #ifdef DRACO
1.77 is 921: dracorev = is_draco();
922: if (dracorev) {
923: if (dracorev >= 4) {
1.93 is 924: vectab[24+1] = DraCoLev1intr;
925: vectab[24+2] = DraCoIntr;
1.77 is 926: } else {
1.93 is 927: vectab[24+1] = DraCoIntr;
928: vectab[24+2] = DraCoLev2intr;
1.77 is 929: }
1.93 is 930: vectab[24+3] = DraCoIntr;
931: vectab[24+4] = DraCoIntr;
932: vectab[24+5] = DraCoIntr;
933: vectab[24+6] = DraCoIntr;
1.70 is 934: }
935: #endif
1.1 mw 936: }
937:
1.61 veego 938: void
1.1 mw 939: straytrap(pc, evec)
940: int pc;
941: u_short evec;
942: {
1.80 christos 943: printf("unexpected trap format %x (vector offset %x) from %x\n",
1.66 is 944: evec>>12, evec & 0xFFF, pc);
1.42 chopps 945: /*XXX*/ panic("straytrap");
1.1 mw 946: }
947:
948: int *nofault;
949:
1.61 veego 950: int
1.1 mw 951: badaddr(addr)
952: register caddr_t addr;
953: {
954: register int i;
955: label_t faultbuf;
956:
957: #ifdef lint
958: i = *addr; if (i) return(0);
959: #endif
960: nofault = (int *) &faultbuf;
961: if (setjmp((label_t *)nofault)) {
962: nofault = (int *) 0;
963: return(1);
964: }
965: i = *(volatile short *)addr;
966: nofault = (int *) 0;
967: return(0);
968: }
969:
1.61 veego 970: int
1.1 mw 971: badbaddr(addr)
972: register caddr_t addr;
973: {
974: register int i;
975: label_t faultbuf;
976:
977: #ifdef lint
978: i = *addr; if (i) return(0);
979: #endif
980: nofault = (int *) &faultbuf;
981: if (setjmp((label_t *)nofault)) {
982: nofault = (int *) 0;
983: return(1);
984: }
985: i = *(volatile char *)addr;
986: nofault = (int *) 0;
987: return(0);
988: }
989:
1.61 veego 990: static void
1.1 mw 991: netintr()
992: {
1.147 erh 993:
994: #define DONETISR(bit, fn) do { \
995: if (netisr & (1 << bit)) { \
996: netisr &= ~(1 << bit); \
997: fn(); \
998: } \
999: } while (0)
1000:
1001: #include <net/netisr_dispatch.h>
1002:
1003: #undef DONETISR
1.1 mw 1004: }
1005:
1.3 mw 1006:
1.31 chopps 1007: /*
1008: * this is a handy package to have asynchronously executed
1009: * function calls executed at very low interrupt priority.
1.166 aymeric 1010: * Example for use is keyboard repeat, where the repeat
1.31 chopps 1011: * handler running at splclock() triggers such a (hardware
1012: * aided) software interrupt.
1013: * Note: the installed functions are currently called in a
1014: * LIFO fashion, might want to change this to FIFO
1015: * later.
1016: */
1.3 mw 1017: struct si_callback {
1.31 chopps 1018: struct si_callback *next;
1.166 aymeric 1019: void (*function)(void *rock1, void *rock2);
1.31 chopps 1020: void *rock1, *rock2;
1.3 mw 1021: };
1.196 aymeric 1022:
1023: struct softintr {
1024: int pending;
1025: void (*function)(void *);
1026: void *arg;
1027: };
1028:
1.31 chopps 1029: static struct si_callback *si_callbacks;
1.42 chopps 1030: static struct si_callback *si_free;
1031: #ifdef DIAGNOSTIC
1032: static int ncb; /* number of callback blocks allocated */
1033: static int ncbd; /* number of callback blocks dynamically allocated */
1034: #endif
1035:
1.95 is 1036: /*
1037: * these are __GENERIC_SOFT_INTERRUPT wrappers; will be replaced
1038: * once by the real thing once all drivers are converted.
1039: *
1040: * to help performance for converted drivers, the YYY_sicallback() function
1041: * family can be implemented in terms of softintr_XXX() as an intermediate
1042: * measure.
1043: */
1044:
1045: static void
1046: _softintr_callit(rock1, rock2)
1047: void *rock1, *rock2;
1048: {
1.196 aymeric 1049: struct softintr *si = rock1;
1050:
1051: si->pending = 0;
1052: si->function(si->arg);
1.95 is 1053: }
1054:
1055: void *
1056: softintr_establish(ipl, func, arg)
1057: int ipl;
1.166 aymeric 1058: void func(void *);
1.95 is 1059: void *arg;
1060: {
1.196 aymeric 1061: struct softintr *si;
1.95 is 1062:
1.196 aymeric 1063: si = malloc(sizeof *si, M_TEMP, M_NOWAIT);
1.95 is 1064: if (si == NULL)
1.196 aymeric 1065: return si;
1.95 is 1066:
1.196 aymeric 1067: si->pending = 0;
1068: si->function = func;
1069: si->arg = arg;
1.95 is 1070:
1071: alloc_sicallback();
1072: return ((void *)si);
1073: }
1074:
1.127 is 1075: void
1076: softintr_disestablish(hook)
1077: void *hook;
1078: {
1079: /*
1.178 wiz 1080: * XXX currently, there is a memory leak here; we can't free the
1.127 is 1081: * sicallback structure.
1.178 wiz 1082: * this will be automatically repaired once we rewrite the soft
1083: * interrupt functions.
1.127 is 1084: */
1.166 aymeric 1085:
1.127 is 1086: free(hook, M_TEMP);
1087: }
1.95 is 1088:
1.42 chopps 1089: void
1090: alloc_sicallback()
1091: {
1092: struct si_callback *si;
1093: int s;
1094:
1095: si = (struct si_callback *)malloc(sizeof(*si), M_TEMP, M_NOWAIT);
1096: if (si == NULL)
1097: return;
1098: s = splhigh();
1099: si->next = si_free;
1100: si_free = si;
1101: splx(s);
1102: #ifdef DIAGNOSTIC
1103: ++ncb;
1104: #endif
1.95 is 1105: }
1106:
1107: void
1108: softintr_schedule(vsi)
1109: void *vsi;
1110: {
1.196 aymeric 1111: struct softintr *si = vsi;
1.95 is 1112:
1.196 aymeric 1113: if (si->pending == 0) {
1114: si->pending = 1;
1115: add_sicallback(_softintr_callit, si, NULL);
1116: }
1.42 chopps 1117: }
1.3 mw 1118:
1119: void
1120: add_sicallback (function, rock1, rock2)
1.166 aymeric 1121: void (*function)(void *rock1, void *rock2);
1.31 chopps 1122: void *rock1, *rock2;
1.3 mw 1123: {
1.31 chopps 1124: struct si_callback *si;
1125: int s;
1.3 mw 1126:
1.31 chopps 1127: /*
1128: * this function may be called from high-priority interrupt handlers.
1129: * We may NOT block for memory-allocation in here!.
1130: */
1.42 chopps 1131: s = splhigh();
1132: si = si_free;
1133: if (si != NULL)
1134: si_free = si->next;
1135: splx(s);
1136:
1137: if (si == NULL) {
1138: si = (struct si_callback *)malloc(sizeof(*si), M_TEMP, M_NOWAIT);
1139: #ifdef DIAGNOSTIC
1140: if (si)
1141: ++ncbd; /* count # dynamically allocated */
1142: #endif
1.3 mw 1143:
1.42 chopps 1144: if (!si)
1145: return;
1146: }
1.3 mw 1147:
1.31 chopps 1148: si->function = function;
1149: si->rock1 = rock1;
1150: si->rock2 = rock2;
1.3 mw 1151:
1.31 chopps 1152: s = splhigh();
1153: si->next = si_callbacks;
1154: si_callbacks = si;
1155: splx(s);
1.3 mw 1156:
1.31 chopps 1157: /*
1.45 chopps 1158: * Cause a software interrupt (spl1). This interrupt might
1.31 chopps 1159: * happen immediately, or after returning to a safe enough level.
1160: */
1.45 chopps 1161: setsoftcback();
1.3 mw 1162: }
1163:
1164:
1165: void
1.31 chopps 1166: rem_sicallback(function)
1.166 aymeric 1167: void (*function)(void *rock1, void *rock2);
1.3 mw 1168: {
1.31 chopps 1169: struct si_callback *si, *psi, *nsi;
1170: int s;
1.3 mw 1171:
1.31 chopps 1172: s = splhigh();
1173: for (psi = 0, si = si_callbacks; si; ) {
1174: nsi = si->next;
1.3 mw 1175:
1.31 chopps 1176: if (si->function != function)
1177: psi = si;
1178: else {
1.42 chopps 1179: /* free(si, M_TEMP); */
1180: si->next = si_free;
1181: si_free = si;
1.31 chopps 1182: if (psi)
1183: psi->next = nsi;
1184: else
1185: si_callbacks = nsi;
1186: }
1187: si = nsi;
1.3 mw 1188: }
1.31 chopps 1189: splx(s);
1.3 mw 1190: }
1191:
1192: /* purge the list */
1193: static void
1.31 chopps 1194: call_sicallbacks()
1.3 mw 1195: {
1.31 chopps 1196: struct si_callback *si;
1197: int s;
1.42 chopps 1198: void *rock1, *rock2;
1.166 aymeric 1199: void (*function)(void *, void *);
1.3 mw 1200:
1.31 chopps 1201: do {
1202: s = splhigh ();
1.61 veego 1203: if ((si = si_callbacks) != 0)
1.31 chopps 1204: si_callbacks = si->next;
1205: splx(s);
1206:
1207: if (si) {
1.42 chopps 1208: function = si->function;
1209: rock1 = si->rock1;
1210: rock2 = si->rock2;
1211: /* si->function(si->rock1, si->rock2); */
1212: /* free(si, M_TEMP); */
1213: s = splhigh ();
1214: si->next = si_free;
1215: si_free = si;
1216: splx(s);
1217: function (rock1, rock2);
1.31 chopps 1218: }
1219: } while (si);
1.42 chopps 1220: #ifdef DIAGNOSTIC
1221: if (ncbd) {
1.44 chopps 1222: ncb += ncbd;
1.80 christos 1223: printf("call_sicallback: %d more dynamic structures %d total\n",
1.42 chopps 1224: ncbd, ncb);
1225: ncbd = 0;
1226: }
1227: #endif
1.3 mw 1228: }
1229:
1.45 chopps 1230: struct isr *isr_ports;
1.66 is 1231: #ifdef DRACO
1232: struct isr *isr_slot3;
1.81 is 1233: struct isr *isr_supio;
1.66 is 1234: #endif
1.45 chopps 1235: struct isr *isr_exter;
1236:
1237: void
1238: add_isr(isr)
1239: struct isr *isr;
1240: {
1241: struct isr **p, *q;
1242:
1.66 is 1243: #ifdef DRACO
1244: switch (isr->isr_ipl) {
1245: case 2:
1246: p = &isr_ports;
1247: break;
1248: case 3:
1249: p = &isr_slot3;
1250: break;
1.81 is 1251: case 5:
1252: p = &isr_supio;
1253: break;
1.70 is 1254: default: /* was case 6:; make gcc -Wall quiet */
1.66 is 1255: p = &isr_exter;
1256: break;
1257: }
1258: #else
1.45 chopps 1259: p = isr->isr_ipl == 2 ? &isr_ports : &isr_exter;
1.66 is 1260: #endif
1.45 chopps 1261: while ((q = *p) != NULL)
1262: p = &q->isr_forw;
1263: isr->isr_forw = NULL;
1264: *p = isr;
1265: /* enable interrupt */
1.66 is 1266: #ifdef DRACO
1267: if (is_draco())
1.81 is 1268: switch(isr->isr_ipl) {
1269: case 6:
1.122 is 1270: single_inst_bset_b(*draco_intena, DRIRQ_INT6);
1.81 is 1271: break;
1272: case 2:
1.122 is 1273: single_inst_bset_b(*draco_intena, DRIRQ_INT2);
1.81 is 1274: break;
1275: default:
1276: break;
1277: }
1.166 aymeric 1278: else
1.66 is 1279: #endif
1.166 aymeric 1280: custom.intena = isr->isr_ipl == 2 ?
1.66 is 1281: INTF_SETCLR | INTF_PORTS :
1282: INTF_SETCLR | INTF_EXTER;
1.45 chopps 1283: }
1284:
1285: void
1286: remove_isr(isr)
1287: struct isr *isr;
1288: {
1289: struct isr **p, *q;
1290:
1.66 is 1291: #ifdef DRACO
1292: switch (isr->isr_ipl) {
1293: case 2:
1294: p = &isr_ports;
1295: break;
1296: case 3:
1297: p = &isr_slot3;
1298: break;
1.81 is 1299: case 5:
1300: p = &isr_supio;
1301: break;
1.70 is 1302: default: /* XXX to make gcc -Wall quiet, was 6: */
1.66 is 1303: p = &isr_exter;
1304: break;
1305: }
1306: #else
1.45 chopps 1307: p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
1.66 is 1308: #endif
1309:
1.45 chopps 1310: while ((q = *p) != NULL && q != isr)
1311: p = &q->isr_forw;
1312: if (q)
1313: *p = q->isr_forw;
1314: else
1315: panic("remove_isr: handler not registered");
1316: /* disable interrupt if no more handlers */
1.66 is 1317: #ifdef DRACO
1318: switch (isr->isr_ipl) {
1319: case 2:
1320: p = &isr_ports;
1321: break;
1322: case 3:
1323: p = &isr_slot3;
1324: break;
1.81 is 1325: case 5:
1326: p = &isr_supio;
1327: break;
1.66 is 1328: case 6:
1329: p = &isr_exter;
1330: break;
1331: }
1332: #else
1.45 chopps 1333: p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
1.66 is 1334: #endif
1.128 is 1335: if (*p == NULL) {
1.66 is 1336: #ifdef DRACO
1.81 is 1337: if (is_draco()) {
1338: switch(isr->isr_ipl) {
1339: case 2:
1.122 is 1340: single_inst_bclr_b(*draco_intena,
1341: DRIRQ_INT2);
1.81 is 1342: break;
1343: case 6:
1.122 is 1344: single_inst_bclr_b(*draco_intena,
1345: DRIRQ_INT6);
1.81 is 1346: break;
1347: default:
1348: break;
1349: }
1350: } else
1.66 is 1351: #endif
1.166 aymeric 1352: custom.intena = isr->isr_ipl == 6 ?
1.66 is 1353: INTF_EXTER : INTF_PORTS;
1.128 is 1354: }
1.45 chopps 1355: }
1356:
1.61 veego 1357: void
1.1 mw 1358: intrhand(sr)
1359: int sr;
1360: {
1.22 chopps 1361: register unsigned int ipl;
1362: register unsigned short ireq;
1.45 chopps 1363: register struct isr **p, *q;
1.1 mw 1364:
1.22 chopps 1365: ipl = (sr >> 8) & 7;
1.66 is 1366: #ifdef REALLYDEBUG
1.80 christos 1367: printf("intrhand: got int. %d\n", ipl);
1.66 is 1368: #endif
1369: #ifdef DRACO
1370: if (is_draco())
1371: ireq = ((ipl == 1) && (*draco_intfrc & DRIRQ_SOFT) ?
1372: INTF_SOFTINT : 0);
1373: else
1374: #endif
1375: ireq = custom.intreqr;
1.1 mw 1376:
1.22 chopps 1377: switch (ipl) {
1378: case 1:
1.66 is 1379: #ifdef DRACO
1380: if (is_draco() && (draco_ioct->io_status & DRSTAT_KBDRECV))
1381: drkbdintr();
1382: #endif
1.22 chopps 1383: if (ireq & INTF_TBE) {
1384: #if NSER > 0
1385: ser_outintr();
1386: #else
1387: custom.intreq = INTF_TBE;
1388: #endif
1389: }
1390:
1391: if (ireq & INTF_DSKBLK) {
1.17 chopps 1392: #if NFD > 0
1.22 chopps 1393: fdintr(0);
1.17 chopps 1394: #endif
1.22 chopps 1395: custom.intreq = INTF_DSKBLK;
1396: }
1397: if (ireq & INTF_SOFTINT) {
1.61 veego 1398: unsigned char ssir_active;
1399: int s;
1400:
1.22 chopps 1401: /*
1.36 chopps 1402: * first clear the softint-bit
1.45 chopps 1403: * then process all classes of softints.
1.166 aymeric 1404: * this order is dicated by the nature of
1.36 chopps 1405: * software interrupts. The other order
1.61 veego 1406: * allows software interrupts to be missed.
1407: * Also copy and clear ssir to prevent
1408: * interrupt loss.
1.22 chopps 1409: */
1.45 chopps 1410: clrsoftint();
1.61 veego 1411: s = splhigh();
1412: ssir_active = ssir;
1.158 is 1413: siroff(SIR_NET | SIR_CBACK);
1.61 veego 1414: splx(s);
1415: if (ssir_active & SIR_NET) {
1.66 is 1416: #ifdef REALLYDEBUG
1.80 christos 1417: printf("calling netintr\n");
1.66 is 1418: #endif
1.121 mhitch 1419: uvmexp.softs++;
1.45 chopps 1420: netintr();
1421: }
1.61 veego 1422: if (ssir_active & SIR_CBACK) {
1.66 is 1423: #ifdef REALLYDEBUG
1.80 christos 1424: printf("calling softcallbacks\n");
1.66 is 1425: #endif
1.121 mhitch 1426: uvmexp.softs++;
1.45 chopps 1427: call_sicallbacks();
1428: }
1.22 chopps 1429: }
1430: break;
1431:
1432: case 2:
1.45 chopps 1433: p = &isr_ports;
1434: while ((q = *p) != NULL) {
1435: if ((q->isr_intr)(q->isr_arg))
1436: break;
1437: p = &q->isr_forw;
1438: }
1439: if (q == NULL)
1440: ciaa_intr ();
1.66 is 1441: #ifdef DRACO
1442: if (is_draco())
1.122 is 1443: single_inst_bclr_b(*draco_intpen, DRIRQ_INT2);
1.66 is 1444: else
1445: #endif
1446: custom.intreq = INTF_PORTS;
1.104 is 1447:
1.22 chopps 1448: break;
1.104 is 1449:
1450: #ifdef DRACO
1451: /* only handled here for DraCo */
1452: case 6:
1453: p = &isr_exter;
1454: while ((q = *p) != NULL) {
1455: if ((q->isr_intr)(q->isr_arg))
1456: break;
1457: p = &q->isr_forw;
1458: }
1.122 is 1459: single_inst_bclr_b(*draco_intpen, DRIRQ_INT6);
1.104 is 1460: break;
1461: #endif
1462:
1.166 aymeric 1463: case 3:
1.104 is 1464: /* VBL */
1.166 aymeric 1465: if (ireq & INTF_BLIT)
1.22 chopps 1466: blitter_handler();
1.166 aymeric 1467: if (ireq & INTF_COPER)
1.22 chopps 1468: copper_handler();
1.166 aymeric 1469: if (ireq & INTF_VERTB)
1.22 chopps 1470: vbl_handler();
1471: break;
1.81 is 1472: #ifdef DRACO
1473: case 5:
1474: p = &isr_supio;
1475: while ((q = *p) != NULL) {
1476: if ((q->isr_intr)(q->isr_arg))
1477: break;
1478: p = &q->isr_forw;
1479: }
1480: break;
1481: #endif
1.3 mw 1482: #if 0
1483: /* now dealt with in locore.s for speed reasons */
1.22 chopps 1484: case 5:
1485: /* check RS232 RBF */
1486: serintr (0);
1487:
1488: custom.intreq = INTF_DSKSYNC;
1489: break;
1490: #endif
1491:
1492: case 4:
1.66 is 1493: #ifdef DRACO
1494: #include "drsc.h"
1495: if (is_draco())
1496: #if NDRSC > 0
1497: drsc_handler();
1498: #else
1.122 is 1499: single_inst_bclr_b(*draco_intpen, DRIRQ_SCSI);
1.66 is 1500: #endif
1501: else
1502: #endif
1.22 chopps 1503: audio_handler();
1504: break;
1505: default:
1.80 christos 1506: printf("intrhand: unexpected sr 0x%x, intreq = 0x%x\n",
1.22 chopps 1507: sr, ireq);
1508: break;
1509: }
1.66 is 1510: #ifdef REALLYDEBUG
1.80 christos 1511: printf("intrhand: leaving.\n");
1.66 is 1512: #endif
1.1 mw 1513: }
1514:
1515: #if defined(DEBUG) && !defined(PANICBUTTON)
1516: #define PANICBUTTON
1517: #endif
1518:
1519: #ifdef PANICBUTTON
1520: int panicbutton = 1; /* non-zero if panic buttons are enabled */
1521: int crashandburn = 0;
1522: int candbdelay = 50; /* give em half a second */
1.166 aymeric 1523: void candbtimer(void);
1.148 thorpej 1524: struct callout candbtimer_ch = CALLOUT_INITIALIZER;
1.1 mw 1525:
1.61 veego 1526: void
1.1 mw 1527: candbtimer()
1528: {
1529: crashandburn = 0;
1530: }
1531: #endif
1532:
1533: #if 0
1534: /*
1535: * Level 7 interrupts can be caused by the keyboard or parity errors.
1536: */
1537: nmihand(frame)
1538: struct frame frame;
1539: {
1540: if (kbdnmi()) {
1541: #ifdef PANICBUTTON
1542: static int innmihand = 0;
1543:
1544: /*
1545: * Attempt to reduce the window of vulnerability for recursive
1546: * NMIs (e.g. someone holding down the keyboard reset button).
1547: */
1548: if (innmihand == 0) {
1549: innmihand = 1;
1.80 christos 1550: printf("Got a keyboard NMI\n");
1.1 mw 1551: innmihand = 0;
1552: }
1553: if (panicbutton) {
1554: if (crashandburn) {
1555: crashandburn = 0;
1556: panic(panicstr ?
1557: "forced crash, nosync" : "forced crash");
1558: }
1559: crashandburn++;
1.148 thorpej 1560: callout_reset(&candbtimer_ch, candbdelay,
1561: candbtimer, NULL);
1.1 mw 1562: }
1563: #endif
1564: return;
1565: }
1566: if (parityerror(&frame))
1567: return;
1568: /* panic?? */
1.80 christos 1569: printf("unexpected level 7 interrupt ignored\n");
1.1 mw 1570: }
1571: #endif
1572:
1.31 chopps 1573: /*
1574: * should only get here, if no standard executable. This can currently
1575: * only mean, we're reading an old ZMAGIC file without MID, but since Amiga
1576: * ZMAGIC always worked the `right' way (;-)) just ignore the missing
1577: * MID and proceed to new zmagic code ;-)
1578: */
1.61 veego 1579: int
1.194 christos 1580: cpu_exec_aout_makecmds(l, epp)
1581: struct lwp *l;
1.31 chopps 1582: struct exec_package *epp;
1.1 mw 1583: {
1.31 chopps 1584: int error = ENOEXEC;
1.71 veego 1585: #ifdef COMPAT_NOMID
1.31 chopps 1586: struct exec *execp = epp->ep_hdr;
1.71 veego 1587: #endif
1.1 mw 1588:
1589: #ifdef COMPAT_NOMID
1.31 chopps 1590: if (!((execp->a_midmag >> 16) & 0x0fff)
1591: && execp->a_midmag == ZMAGIC)
1.194 christos 1592: return(exec_aout_prep_zmagic(l, epp));
1.4 mw 1593: #endif
1.31 chopps 1594: return(error);
1.4 mw 1595: }
1.162 is 1596:
1597: #ifdef LKM
1598:
1599: int _spllkm6(void);
1600: int _spllkm7(void);
1601:
1602: #ifdef LEV6_DEFER
1603: int _spllkm6() {
1604: return spl4();
1605: };
1606:
1607: int _spllkm7() {
1608: return spl4();
1609: };
1610:
1611: #else
1612:
1613: int _spllkm6() {
1614: return spl6();
1615: };
1616:
1617: int _spllkm7() {
1618: return spl7();
1.166 aymeric 1619: };
1.162 is 1620:
1621: #endif
1622:
1623: #endif
CVSweb <webmaster@jp.NetBSD.org>