NetBSD-5.0.2/sys/arch/vax/vax/locore.c
/* $NetBSD: locore.c,v 1.75 2008/03/11 05:34:03 matt 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed at Ludd, University of Lule}.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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 <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: locore.c,v 1.75 2008/03/11 05:34:03 matt Exp $");
#include "opt_compat_netbsd.h"
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
#include <machine/sid.h>
#include <machine/param.h>
#include <machine/vmparam.h>
#include <machine/pcb.h>
#include <machine/pte.h>
#include <machine/pmap.h>
#include <machine/nexus.h>
#include <machine/rpb.h>
#include "opt_cputype.h"
void _start(struct rpb *);
void main(void);
extern paddr_t avail_end;
paddr_t esym;
struct user *proc0paddr;
/*
* The strict CPU-dependent information is set up here, in
* form of a pointer to a struct that is specific for each CPU.
*/
extern const struct cpu_dep ka780_calls;
extern const struct cpu_dep ka750_calls;
extern const struct cpu_dep ka860_calls;
extern const struct cpu_dep ka820_calls;
extern const struct cpu_dep ka6400_calls;
extern const struct cpu_dep ka88_calls;
extern const struct cpu_dep ka43_calls;
extern const struct cpu_dep ka46_calls;
extern const struct cpu_dep ka48_calls;
extern const struct cpu_dep vxt_calls;
extern const struct cpu_dep ka49_calls;
extern const struct cpu_dep ka53_calls;
extern const struct cpu_dep ka410_calls;
extern const struct cpu_dep ka610_calls;
extern const struct cpu_dep ka630_calls;
extern const struct cpu_dep ka650_calls;
extern const struct cpu_dep ka660_calls;
extern const struct cpu_dep ka670_calls;
extern const struct cpu_dep ka680_calls;
/*
* Start is called from boot; the first routine that is called
* in kernel. Kernel stack is setup somewhere in a safe place;
* but we need to move it to a better known place. Memory
* management is disabled, and no interrupt system is active.
*/
void
_start(struct rpb *prpb)
{
extern uintptr_t scratch;
struct pte *pt;
mtpr(AST_NO, PR_ASTLVL); /* Turn off ASTs */
findcpu(); /* Set up the CPU identifying variables */
cpu_model[0] = 0; /* Be sure */
if (vax_confdata & 0x80)
strcpy(cpu_model, "MicroVAX ");
else
strcpy(cpu_model, "VAXstation ");
switch (vax_boardtype) {
#if VAX780 || VAXANY
case VAX_BTYP_780:
dep_call = &ka780_calls;
strcpy(cpu_model,"VAX 11/780");
if (vax_cpudata & 0x100)
cpu_model[9] = '5';
break;
#endif
#if VAX750 || VAXANY
case VAX_BTYP_750:
dep_call = &ka750_calls;
strcpy(cpu_model, "VAX 11/750");
break;
#endif
#if VAX8600 || VAXANY
case VAX_BTYP_790:
dep_call = &ka860_calls;
strcpy(cpu_model,"VAX 8600");
if (vax_cpudata & 0x800000)
cpu_model[6] = '5';
break;
#endif
#if VAX410 || VAXANY
case VAX_BTYP_420: /* They are very similar */
dep_call = &ka410_calls;
strcat(cpu_model, "3100");
if (((vax_siedata >> 8) & 0xff) == 1)
strcat(cpu_model, "/m{38,48}");
else if (((vax_siedata >> 8) & 0xff) == 0)
strcat(cpu_model, "/m{30,40}");
break;
case VAX_BTYP_410:
dep_call = &ka410_calls;
strcat(cpu_model, "2000");
break;
#endif
#if VAX43 || VAXANY
case VAX_BTYP_43:
dep_call = &ka43_calls;
strcat(cpu_model, "3100/m76");
break;
#endif
#if VAX46 || VAXANY
case VAX_BTYP_46:
dep_call = &ka46_calls;
switch(vax_siedata & 0x3) {
case 1: strcpy(cpu_model, "MicroVAX 3100/80"); break;
case 2: strcpy(cpu_model, "VAXstation 4000/60"); break;
default: strcpy(cpu_model, "unknown"); break;
}
break;
#endif
#if VAX48 || VAXANY
case VAX_BTYP_48:
dep_call = &ka48_calls;
switch (vax_siedata & 3) {
case 1: strcpy(cpu_model, "MicroVAX 3100/m{30,40}"); break;
case 2: strcpy(cpu_model, "VAXstation 4000 VLC"); break;
default: strcpy(cpu_model, "unknown SOC"); break;
}
break;
#endif
#if 0 && (VXT2000 || VAXANY)
case VAX_BTYP_VXT:
dep_call = &vxt_calls;
strcpy(cpu_model, "VXT 2000 X terminal");
break;
#endif
#if VAX49 || VAXANY
case VAX_BTYP_49:
dep_call = &ka49_calls;
strcat(cpu_model, "4000/90");
break;
#endif
#if VAX53 || VAXANY
case VAX_BTYP_53:
dep_call = &ka53_calls;
switch((vax_siedata & 0xff00) >> 8) {
case VAX_STYP_51:
strcpy(cpu_model, "MicroVAX 3100/m{90,95}"); break;
case VAX_STYP_52:
strcpy(cpu_model, "VAX 4000/100"); break;
case VAX_STYP_53:
strcpy(cpu_model, "VAX 4000/{105A,106A,108}"); break;
case VAX_STYP_55:
strcpy(cpu_model, "MicroVAX 3100/m85"); break;
default:
strcpy(cpu_model,"unknown 1303");
}
break;
#endif
#if VAX610 || VAXANY
case VAX_BTYP_610:
dep_call = &ka610_calls;
strcpy(cpu_model,"MicroVAX I");
break;
#endif
#if VAX630 || VAXANY
case VAX_BTYP_630:
dep_call = &ka630_calls;
strcpy(cpu_model,"MicroVAX II");
break;
#endif
#if VAX650 || VAXANY
case VAX_BTYP_650:
dep_call = &ka650_calls;
strcpy(cpu_model,"MicroVAX ");
switch ((vax_siedata >> 8) & 255) {
case VAX_SIE_KA640:
strcat(cpu_model, "3300/3400");
break;
case VAX_SIE_KA650:
strcat(cpu_model, "3500/3600");
break;
case VAX_SIE_KA655:
strcat(cpu_model, "3800/3900");
break;
default:
strcat(cpu_model, "III");
break;
}
break;
#endif
#if VAX660 || VAXANY
case VAX_BTYP_660:
dep_call = &ka660_calls;
strcpy(cpu_model,"VAX 4000/200");
break;
#endif
#if VAX670 || VAXANY
case VAX_BTYP_670:
dep_call = &ka670_calls;
strcpy(cpu_model,"VAX 4000/300");
break;
#endif
#if VAX680 || VAXANY
case VAX_BTYP_680:
dep_call = &ka680_calls;
switch((vax_siedata & 0xff00) >> 8) {
case VAX_STYP_675:
strcpy(cpu_model,"VAX 4000/400"); break;
case VAX_STYP_680:
strcpy(cpu_model,"VAX 4000/500"); break;
default:
strcpy(cpu_model,"unknown 1301");
}
break;
case VAX_BTYP_681:
dep_call = &ka680_calls;
switch((vax_siedata & 0xff00) >> 8) {
case VAX_STYP_681:
strcpy(cpu_model,"VAX 4000/500A"); break;
case VAX_STYP_691:
strcpy(cpu_model,"VAX 4000/600A"); break;
case VAX_STYP_694:
strcpy(cpu_model,"VAX 4000/700A");
if (vax_cpudata & 0x1000) /* 705A */
cpu_model[sizeof("VAX 4000/70") - 1] = '5';
break;
default:
strcpy(cpu_model,"unknown 1305");
}
break;
#endif
#if VAX8200 || VAXANY
case VAX_BTYP_8000:
dep_call = &ka820_calls;
strcpy(cpu_model, "VAX 8200");
break;
#endif
#if VAX8800 || VAXANY
case VAX_BTYP_8PS:
case VAX_BTYP_8800: /* Matches all other KA88-machines also */
strcpy(cpu_model, "VAX 8800");
dep_call = &ka88_calls;
break;
#endif
#if VAX6400 || VAXANY
case VAX_BTYP_9RR:
/* cpu_model set in steal_pages */
dep_call = &ka6400_calls;
break;
#endif
default:
/* CPU not supported, just give up */
__asm("halt");
}
/*
* Machines older than MicroVAX II have their boot blocks
* loaded directly or the boot program loaded from console
* media, so we need to figure out their memory size.
* This is not easily done on MicroVAXen, so we get it from
* VMB instead.
*
* In post-1.4 a RPB is always provided from the boot blocks.
*/
#if defined(COMPAT_14)
if (prpb == 0) {
memset((char *)proc0paddr + REDZONEADDR, 0, sizeof(struct rpb));
prpb = (struct rpb *)(proc0paddr + REDZONEADDR);
prpb->pfncnt = avail_end >> VAX_PGSHIFT;
prpb->rpb_base = (void *)-1; /* RPB is fake */
} else
#endif
memcpy((char *)proc0paddr + REDZONEADDR, prpb, sizeof(struct rpb));
if (prpb->pfncnt)
avail_end = prpb->pfncnt << VAX_PGSHIFT;
else
while (badaddr((void *)avail_end, 4) == 0)
avail_end += VAX_NBPG * 128;
boothowto = prpb->rpb_bootr5;
avail_end &= ~PGOFSET; /* be sure */
lwp0.l_addr = (void *)proc0paddr; /* XXX */
pmap_bootstrap();
/* Now running virtual. set red zone for proc0 */
pt = kvtopte((u_int)lwp0.l_addr + REDZONEADDR);
pt->pg_v = 0;
((struct pcb *)proc0paddr)->framep = (void *)scratch;
/*
* Change mode down to userspace is done by faking a stack
* frame that is setup in cpu_set_kpc(). Not done by returning
* from main anymore.
*/
main();
/* NOTREACHED */
}