/* $NetBSD: autoconf.c,v 1.29 2017/05/22 16:59:32 ragge Exp $ */ /* * Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* All bugs are subject to removal without further notice */ #include #include #include #include "../include/mtpr.h" #include "../include/sid.h" #include "../include/intr.h" #include "../include/rpb.h" #include "../include/scb.h" #include "vaxstand.h" void autoconf(void); void findcpu(void); void consinit(void); void scbinit(void); void scb_stray(void *); void longjmp(int *, int); void rtimer(void *); long *bootregs; /* * Do some initial setup. Also create a fake RPB for net-booted machines * that don't have an in-prom VMB. */ void autoconf(void) { int copyrpb = 1; int fromnet = (bootregs[12] != -1); findcpu(); /* Configures CPU variables */ consinit(); /* Allow us to print out things */ scbinit(); /* Fix interval clock etc */ #ifdef DEV_DEBUG printf("Register contents:\n"); for (copyrpb = 0; copyrpb < 13; copyrpb++) printf("r%d: %lx\n", copyrpb, bootregs[copyrpb]); #endif switch (vax_boardtype) { case VAX_BTYP_780: case VAX_BTYP_790: case VAX_BTYP_8000: case VAX_BTYP_9CC: case VAX_BTYP_9RR: case VAX_BTYP_1202: if (fromnet == 0) break; copyrpb = 0; bootrpb.devtyp = bootregs[0]; bootrpb.adpphy = bootregs[1]; bootrpb.csrphy = bootregs[2]; bootrpb.unit = bootregs[3]; bootrpb.rpb_bootr5 = bootregs[5]; bootrpb.pfncnt = 0; break; case VAX_BTYP_46: case VAX_BTYP_48: {int *map, i; /* Map all 16MB of I/O space to low 16MB of memory */ map = (int *)0x700000; /* XXX */ *(int *)0x20080008 = (int)map; /* XXX */ for (i = 0; i < 0x8000; i++) map[i] = 0x80000000 | i; }break; break; } if (copyrpb) { struct rpb *prpb = (struct rpb *)bootregs[11]; memcpy(&bootrpb, (void *)prpb, sizeof(struct rpb)); if (prpb->iovec) { bootrpb.iovec = (int)alloc(prpb->iovecsz); memcpy((void *)bootrpb.iovec, (void *)prpb->iovec, prpb->iovecsz); } } } /* * Clock handling routines, needed to do timing in standalone programs. */ volatile int tickcnt; satime_t getsecs(void) { return tickcnt/100; } struct ivec_dsp **scb; struct ivec_dsp *scb_vec; extern struct ivec_dsp idsptch; extern int jbuf[10]; static void mcheck(void *arg) { int off, *mfp = (int *)(void *)&arg; off = (mfp[7]/4 + 8); printf("Machine check, pc=%x, psl=%x\n", mfp[off], mfp[off+1]); longjmp(jbuf, 1); } /* * Init the SCB and set up a handler for all vectors in the lower space, * to detect unwanted interrupts. */ void scbinit(void) { int i, addr; /* * Allocate space. We need one page for the SCB, and 128*20 == 2.5k * for the vectors. The SCB must be on a page boundary. */ i = (int)alloc(VAX_NBPG + 128*sizeof(scb_vec[0])) + VAX_PGOFSET; i &= ~VAX_PGOFSET; mtpr(i, PR_SCBB); scb = (void *)i; scb_vec = (struct ivec_dsp *)(i + VAX_NBPG); for (i = 0; i < 128; i++) { scb[i] = &scb_vec[i]; addr = (int)scb[i]; addr |= SCB_ISTACK; /* Only interrupt stack */ scb[i] = (struct ivec_dsp*)addr; scb_vec[i] = idsptch; scb_vec[i].hoppaddr = scb_stray; scb_vec[i].pushlarg = (void *) (i * 4); scb_vec[i].ev = NULL; } scb_vec[0xc0/4].hoppaddr = rtimer; scb_vec[4/4].hoppaddr = mcheck; if (vax_boardtype != VAX_BTYP_VXT) mtpr(-10000, PR_NICR); /* Load in count register */ mtpr(0x800000d1, PR_ICCS); /* Start clock and enable interrupt */ mtpr(20, PR_IPL); } extern int sluttid, senast, skip; void rtimer(void *arg) { mtpr(IPL_HIGH, PR_IPL); tickcnt++; mtpr(0xc1, PR_ICCS); if (skip) return; if ((vax_boardtype == VAX_BTYP_46) || (vax_boardtype == VAX_BTYP_48) || (vax_boardtype == VAX_BTYP_49)) { int nu = sluttid - getsecs(); if (senast != nu) { mtpr(20, PR_IPL); longjmp(jbuf, 1); } } } #ifdef __ELF__ #define IDSPTCH "idsptch" #define EIDSPTCH "eidsptch" #define CMN_IDSPTCH "cmn_idsptch" #else #define IDSPTCH "_idsptch" #define EIDSPTCH "_eidsptch" #define CMN_IDSPTCH "_cmn_idsptch" #endif __asm( " .text;" " .align 2;" " .globl " IDSPTCH ", " EIDSPTCH ";" IDSPTCH ":;" " pushr $0x3f;" " .word 0x9f16;" " .long " CMN_IDSPTCH ";" " .long 0;" " .long 0;" " .long 0;" EIDSPTCH ":;" CMN_IDSPTCH ":;" " movl (%sp)+,%r0;" " pushl 4(%r0);" " calls $1,*(%r0);" " popr $0x3f;" " rei;" ); /* * Stray interrupt handler. * This function must _not_ save any registers (in the reg save mask). */ void scb_stray(void *arg) { static int vector, ipl; ipl = mfpr(PR_IPL); vector = (int) arg; printf("stray interrupt: vector 0x%x, ipl %d\n", vector, ipl); }