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