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