[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / amiga / amiga

Annotation of src/sys/arch/amiga/amiga/machdep.c, Revision 1.199

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

CVSweb <webmaster@jp.NetBSD.org>