machdep.c revision 1.2
11.2Stsubai/*	$NetBSD: machdep.c,v 1.2 1999/09/14 11:21:27 tsubai Exp $	*/
21.1Sitojun
31.1Sitojun/*-
41.1Sitojun * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
51.1Sitojun * All rights reserved.
61.1Sitojun *
71.1Sitojun * This code is derived from software contributed to The NetBSD Foundation
81.1Sitojun * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
91.1Sitojun * Simulation Facility, NASA Ames Research Center.
101.1Sitojun *
111.1Sitojun * Redistribution and use in source and binary forms, with or without
121.1Sitojun * modification, are permitted provided that the following conditions
131.1Sitojun * are met:
141.1Sitojun * 1. Redistributions of source code must retain the above copyright
151.1Sitojun *    notice, this list of conditions and the following disclaimer.
161.1Sitojun * 2. Redistributions in binary form must reproduce the above copyright
171.1Sitojun *    notice, this list of conditions and the following disclaimer in the
181.1Sitojun *    documentation and/or other materials provided with the distribution.
191.1Sitojun * 3. All advertising materials mentioning features or use of this software
201.1Sitojun *    must display the following acknowledgement:
211.1Sitojun *	This product includes software developed by the NetBSD
221.1Sitojun *	Foundation, Inc. and its contributors.
231.1Sitojun * 4. Neither the name of The NetBSD Foundation nor the names of its
241.1Sitojun *    contributors may be used to endorse or promote products derived
251.1Sitojun *    from this software without specific prior written permission.
261.1Sitojun *
271.1Sitojun * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
281.1Sitojun * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
291.1Sitojun * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
301.1Sitojun * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
311.1Sitojun * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
321.1Sitojun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
331.1Sitojun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
341.1Sitojun * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
351.1Sitojun * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
361.1Sitojun * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
371.1Sitojun * POSSIBILITY OF SUCH DAMAGE.
381.1Sitojun */
391.1Sitojun
401.1Sitojun/*-
411.1Sitojun * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
421.1Sitojun * All rights reserved.
431.1Sitojun *
441.1Sitojun * This code is derived from software contributed to Berkeley by
451.1Sitojun * William Jolitz.
461.1Sitojun *
471.1Sitojun * Redistribution and use in source and binary forms, with or without
481.1Sitojun * modification, are permitted provided that the following conditions
491.1Sitojun * are met:
501.1Sitojun * 1. Redistributions of source code must retain the above copyright
511.1Sitojun *    notice, this list of conditions and the following disclaimer.
521.1Sitojun * 2. Redistributions in binary form must reproduce the above copyright
531.1Sitojun *    notice, this list of conditions and the following disclaimer in the
541.1Sitojun *    documentation and/or other materials provided with the distribution.
551.1Sitojun * 3. All advertising materials mentioning features or use of this software
561.1Sitojun *    must display the following acknowledgement:
571.1Sitojun *	This product includes software developed by the University of
581.1Sitojun *	California, Berkeley and its contributors.
591.1Sitojun * 4. Neither the name of the University nor the names of its contributors
601.1Sitojun *    may be used to endorse or promote products derived from this software
611.1Sitojun *    without specific prior written permission.
621.1Sitojun *
631.1Sitojun * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
641.1Sitojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
651.1Sitojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
661.1Sitojun * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
671.1Sitojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
681.1Sitojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
691.1Sitojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
701.1Sitojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
711.1Sitojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
721.1Sitojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
731.1Sitojun * SUCH DAMAGE.
741.1Sitojun *
751.1Sitojun *	@(#)machdep.c	7.4 (Berkeley) 6/3/91
761.1Sitojun */
771.1Sitojun
781.1Sitojun#include "opt_compat_netbsd.h"
791.1Sitojun#include "opt_ddb.h"
801.1Sitojun#include "opt_memsize.h"
811.1Sitojun#include "opt_initbsc.h"
821.1Sitojun#include "opt_sysv.h"
831.1Sitojun
841.1Sitojun#include <sys/param.h>
851.1Sitojun#include <sys/systm.h>
861.1Sitojun#include <sys/signalvar.h>
871.1Sitojun#include <sys/kernel.h>
881.1Sitojun#include <sys/map.h>
891.1Sitojun#include <sys/proc.h>
901.1Sitojun#include <sys/user.h>
911.1Sitojun#include <sys/exec.h>
921.1Sitojun#include <sys/buf.h>
931.1Sitojun#include <sys/reboot.h>
941.1Sitojun#include <sys/conf.h>
951.1Sitojun#include <sys/file.h>
961.1Sitojun#include <sys/callout.h>
971.1Sitojun#include <sys/malloc.h>
981.1Sitojun#include <sys/mbuf.h>
991.1Sitojun#include <sys/msgbuf.h>
1001.1Sitojun#include <sys/mount.h>
1011.1Sitojun#include <sys/vnode.h>
1021.1Sitojun#include <sys/device.h>
1031.1Sitojun#include <sys/extent.h>
1041.1Sitojun#include <sys/syscallargs.h>
1051.1Sitojun
1061.1Sitojun#ifdef KGDB
1071.1Sitojun#include <sys/kgdb.h>
1081.1Sitojun#endif
1091.1Sitojun
1101.1Sitojun#include <dev/cons.h>
1111.1Sitojun
1121.1Sitojun#include <vm/vm.h>
1131.1Sitojun#include <vm/vm_kern.h>
1141.1Sitojun#include <vm/vm_page.h>
1151.1Sitojun
1161.1Sitojun#include <uvm/uvm_extern.h>
1171.1Sitojun
1181.1Sitojun#include <sys/sysctl.h>
1191.1Sitojun
1201.1Sitojun#include <machine/cpu.h>
1211.1Sitojun#include <machine/cpufunc.h>
1221.1Sitojun#include <machine/psl.h>
1231.1Sitojun#include <machine/bootinfo.h>
1241.1Sitojun#include <machine/bus.h>
1251.1Sitojun#include <sh3/bscreg.h>
1261.1Sitojun#include <sh3/ccrreg.h>
1271.1Sitojun#include <sh3/cpgreg.h>
1281.1Sitojun#include <sh3/intcreg.h>
1291.1Sitojun#include <sh3/pfcreg.h>
1301.1Sitojun#include <sh3/wdtreg.h>
1311.1Sitojun
1321.1Sitojun#include <sys/termios.h>
1331.1Sitojun#include "sci.h"
1341.1Sitojun
1351.1Sitojun/* the following is used externally (sysctl_hw) */
1361.1Sitojunchar machine[] = MACHINE;		/* cpu "architecture" */
1371.1Sitojunchar machine_arch[] = MACHINE_ARCH;	/* machine_arch = "sh3" */
1381.1Sitojun
1391.1Sitojun#ifdef sh3_debug
1401.1Sitojunint cpu_debug_mode = 1;
1411.1Sitojun#else
1421.1Sitojunint cpu_debug_mode = 0;
1431.1Sitojun#endif
1441.1Sitojun
1451.1Sitojunchar cpu_model[120];
1461.1Sitojun
1471.1Sitojunchar bootinfo[BOOTINFO_MAXSIZE];
1481.1Sitojun
1491.1Sitojunint	physmem;
1501.1Sitojunint	dumpmem_low;
1511.1Sitojunint	dumpmem_high;
1521.1Sitojunextern int	boothowto;
1531.1Sitojunint	cpu_class;
1541.1Sitojun
1551.1Sitojunpaddr_t msgbuf_paddr;
1561.1Sitojun
1571.1Sitojunvm_map_t exec_map = NULL;
1581.1Sitojunvm_map_t mb_map = NULL;
1591.1Sitojunvm_map_t phys_map = NULL;
1601.1Sitojun
1611.1Sitojunextern paddr_t avail_start, avail_end;
1621.1Sitojunextern u_long atdevbase;
1631.1Sitojunextern int etext,_start;
1641.1Sitojun
1651.1Sitojun#ifdef	SYSCALL_DEBUG
1661.1Sitojun#define	SCDEBUG_ALL 0x0004
1671.1Sitojunextern int	scdebug;
1681.1Sitojun#endif
1691.1Sitojun
1701.1Sitojun#define IOM_RAM_END	((paddr_t)IOM_RAM_BEGIN + IOM_RAM_SIZE - 1)
1711.1Sitojun
1721.1Sitojun/*
1731.1Sitojun * Extent maps to manage I/O and ISA memory hole space.  Allocate
1741.1Sitojun * storage for 8 regions in each, initially.  Later, ioport_malloc_safe
1751.1Sitojun * will indicate that it's safe to use malloc() to dynamically allocate
1761.1Sitojun * region descriptors.
1771.1Sitojun *
1781.1Sitojun * N.B. At least two regions are _always_ allocated from the iomem
1791.1Sitojun * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
1801.1Sitojun *
1811.1Sitojun * The extent maps are not static!  Machine-dependent ISA and EISA
1821.1Sitojun * routines need access to them for bus address space allocation.
1831.1Sitojun */
1841.1Sitojunstatic	long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
1851.1Sitojunstruct	extent *ioport_ex;
1861.1Sitojunstruct	extent *iomem_ex;
1871.1Sitojunstatic	int ioport_malloc_safe;
1881.1Sitojun
1891.1Sitojunvoid	setup_bootinfo __P((void));
1901.1Sitojunvoid	dumpsys __P((void));
1911.1Sitojunvoid	identifycpu __P((void));
1921.1Sitojunvoid	initSH3 __P((vaddr_t));
1931.1Sitojunvoid	InitializeSci  __P((unsigned char));
1941.1Sitojunvoid	Send16550 __P((int c));
1951.1Sitojunvoid	Init16550 __P((void));
1961.1Sitojunvoid	sh3_cache_on __P((void));
1971.1Sitojunvoid	LoadAndReset __P((char *osimage));
1981.1Sitojunvoid	XLoadAndReset __P((char *osimage));
1991.1Sitojunvoid	Sh3Reset __P((void));
2001.1Sitojun
2011.1Sitojun#include <dev/ic/comreg.h>
2021.1Sitojun#include <dev/ic/comvar.h>
2031.1Sitojun
2041.1Sitojunvoid	consinit __P((void));
2051.1Sitojun
2061.1Sitojun#ifdef COMPAT_NOMID
2071.1Sitojunstatic int exec_nomid	__P((struct proc *, struct exec_package *));
2081.1Sitojun#endif
2091.1Sitojun
2101.1Sitojun
2111.1Sitojun
2121.1Sitojun/*
2131.1Sitojun * Machine-dependent startup code
2141.1Sitojun *
2151.1Sitojun * This is called from main() in kern/main.c.
2161.1Sitojun */
2171.1Sitojunvoid
2181.1Sitojuncpu_startup()
2191.1Sitojun{
2201.1Sitojun	unsigned i;
2211.1Sitojun	caddr_t v;
2221.1Sitojun	int sz;
2231.1Sitojun	int base, residual;
2241.1Sitojun	vaddr_t minaddr, maxaddr;
2251.1Sitojun	vsize_t size;
2261.1Sitojun	struct pcb *pcb;
2271.2Stsubai	char pbuf[9];
2281.1Sitojun	/* int x; */
2291.1Sitojun
2301.1Sitojun	printf(version);
2311.1Sitojun
2321.1Sitojun	sprintf(cpu_model, "Hitachi SH3");
2331.1Sitojun
2341.2Stsubai	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
2351.2Stsubai	printf("total memory = %s\n", pbuf);
2361.1Sitojun
2371.1Sitojun	/*
2381.1Sitojun	 * Find out how much space we need, allocate it,
2391.1Sitojun	 * and then give everything true virtual addresses.
2401.1Sitojun	 */
2411.2Stsubai	sz = (int)allocsys(NULL, NULL);
2421.1Sitojun	if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
2431.1Sitojun		panic("startup: no room for tables");
2441.2Stsubai	if (allocsys(v, NULL) - v != sz)
2451.1Sitojun		panic("startup: table size inconsistency");
2461.1Sitojun
2471.1Sitojun	/*
2481.1Sitojun	 * Now allocate buffers proper.  They are different than the above
2491.1Sitojun	 * in that they usually occupy more virtual memory than physical.
2501.1Sitojun	 */
2511.1Sitojun	size = MAXBSIZE * nbuf;
2521.1Sitojun	buffers = 0;
2531.1Sitojun	if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
2541.1Sitojun		    NULL, UVM_UNKNOWN_OFFSET,
2551.1Sitojun		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
2561.1Sitojun				UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
2571.1Sitojun		panic("cpu_startup: cannot allocate VM for buffers");
2581.1Sitojun	minaddr = (vaddr_t)buffers;
2591.1Sitojun
2601.1Sitojun	if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
2611.1Sitojun		/* don't want to alloc more physical mem than needed */
2621.1Sitojun		bufpages = btoc(MAXBSIZE) * nbuf;
2631.1Sitojun	}
2641.1Sitojun
2651.1Sitojun	base = bufpages / nbuf;
2661.1Sitojun	residual = bufpages % nbuf;
2671.1Sitojun
2681.1Sitojun	for (i = 0; i < nbuf; i++) {
2691.1Sitojun		vsize_t curbufsize;
2701.1Sitojun		vaddr_t curbuf;
2711.1Sitojun		struct vm_page *pg;
2721.1Sitojun
2731.1Sitojun		/*
2741.1Sitojun		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
2751.1Sitojun		 * that MAXBSIZE space, we allocate and map (base+1) pages
2761.1Sitojun		 * for the first "residual" buffers, and then we allocate
2771.1Sitojun		 * "base" pages for the rest.
2781.1Sitojun		 */
2791.1Sitojun		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
2801.1Sitojun		curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
2811.1Sitojun
2821.1Sitojun		while (curbufsize) {
2831.1Sitojun			/*
2841.1Sitojun			 * Attempt to allocate buffers from the first
2851.1Sitojun			 * 16M of RAM to avoid bouncing file system
2861.1Sitojun			 * transfers.
2871.1Sitojun			 */
2881.1Sitojun			pg = uvm_pagealloc(NULL, 0, NULL, 0);
2891.1Sitojun			if (pg == NULL)
2901.1Sitojun				panic("cpu_startup: not enough memory for "
2911.1Sitojun				    "buffer cache");
2921.2Stsubai			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
2931.2Stsubai					VM_PROT_READ|VM_PROT_WRITE);
2941.1Sitojun			curbuf += PAGE_SIZE;
2951.1Sitojun			curbufsize -= PAGE_SIZE;
2961.1Sitojun		}
2971.1Sitojun	}
2981.1Sitojun
2991.1Sitojun	/*
3001.1Sitojun	 * Allocate a submap for exec arguments.  This map effectively
3011.1Sitojun	 * limits the number of processes exec'ing at any time.
3021.1Sitojun	 */
3031.1Sitojun	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
3041.1Sitojun				   16*NCARGS, TRUE, FALSE, NULL);
3051.1Sitojun
3061.1Sitojun	/*
3071.1Sitojun	 * Allocate a submap for physio
3081.1Sitojun	 */
3091.1Sitojun	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
3101.1Sitojun				   VM_PHYS_SIZE, TRUE, FALSE, NULL);
3111.1Sitojun
3121.1Sitojun	/*
3131.1Sitojun	 * Finally, allocate mbuf cluster submap.
3141.1Sitojun	 */
3151.1Sitojun	mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
3161.1Sitojun	    VM_MBUF_SIZE, FALSE, FALSE, NULL);
3171.1Sitojun
3181.1Sitojun	/*
3191.1Sitojun	 * Initialize callouts
3201.1Sitojun	 */
3211.1Sitojun	callfree = callout;
3221.1Sitojun	for (i = 1; i < ncallout; i++)
3231.1Sitojun		callout[i-1].c_next = &callout[i];
3241.1Sitojun
3251.2Stsubai	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
3261.2Stsubai	printf("avail memory = %s\n", pbuf);
3271.2Stsubai	format_bytes(pbuf, sizeof(pbuf), bufpages * CLBYTES);
3281.2Stsubai	printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
3291.1Sitojun
3301.1Sitojun	/*
3311.1Sitojun	 * Set up buffers, so they can be used to read disk labels.
3321.1Sitojun	 */
3331.1Sitojun	bufinit();
3341.1Sitojun
3351.1Sitojun	/* Safe for i/o port allocation to use malloc now. */
3361.1Sitojun	ioport_malloc_safe = 1;
3371.1Sitojun
3381.1Sitojun	curpcb = pcb = &proc0.p_addr->u_pcb;
3391.1Sitojun	pcb->r15 = (int)proc0.p_addr + USPACE - 16;
3401.1Sitojun
3411.1Sitojun	proc0.p_md.md_regs = (struct trapframe *)pcb->r15 - 1;
3421.1Sitojun
3431.1Sitojun#ifdef SYSCALL_DEBUG
3441.1Sitojun	scdebug |= SCDEBUG_ALL;
3451.1Sitojun#endif
3461.1Sitojun
3471.1Sitojun#if 0
3481.1Sitojun	boothowto |= RB_SINGLE;
3491.1Sitojun#endif
3501.1Sitojun}
3511.1Sitojun
3521.1Sitojun/*
3531.1Sitojun * Info for CTL_HW
3541.1Sitojun */
3551.1Sitojunextern	char version[];
3561.1Sitojun
3571.1Sitojun#define CPUDEBUG
3581.1Sitojun
3591.1Sitojun/*
3601.1Sitojun * machine dependent system variables.
3611.1Sitojun */
3621.1Sitojunint
3631.1Sitojuncpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
3641.1Sitojun	int *name;
3651.1Sitojun	u_int namelen;
3661.1Sitojun	void *oldp;
3671.1Sitojun	size_t *oldlenp;
3681.1Sitojun	void *newp;
3691.1Sitojun	size_t newlen;
3701.1Sitojun	struct proc *p;
3711.1Sitojun{
3721.1Sitojun	dev_t consdev;
3731.1Sitojun	struct btinfo_bootpath *bibp;
3741.1Sitojun	struct trapframe *tf;
3751.1Sitojun	char *osimage;
3761.1Sitojun
3771.1Sitojun	/* all sysctl names at this level are terminal */
3781.1Sitojun	if (namelen != 1)
3791.1Sitojun		return (ENOTDIR);		/* overloaded */
3801.1Sitojun
3811.1Sitojun	switch (name[0]) {
3821.1Sitojun	case CPU_CONSDEV:
3831.1Sitojun		if (cn_tab != NULL)
3841.1Sitojun			consdev = cn_tab->cn_dev;
3851.1Sitojun		else
3861.1Sitojun			consdev = NODEV;
3871.1Sitojun		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
3881.1Sitojun		    sizeof consdev));
3891.1Sitojun
3901.1Sitojun	case CPU_NKPDE:
3911.1Sitojun		return (sysctl_rdint(oldp, oldlenp, newp, nkpde));
3921.1Sitojun
3931.1Sitojun	case CPU_BOOTED_KERNEL:
3941.1Sitojun	        bibp = lookup_bootinfo(BTINFO_BOOTPATH);
3951.1Sitojun	        if (!bibp)
3961.1Sitojun			return (ENOENT); /* ??? */
3971.1Sitojun		return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
3981.1Sitojun
3991.1Sitojun	case CPU_SETPRIVPROC:
4001.1Sitojun		if (newp == NULL)
4011.1Sitojun			return (0);
4021.1Sitojun
4031.1Sitojun		/* set current process to priviledged process */
4041.1Sitojun		tf = p->p_md.md_regs;
4051.1Sitojun		tf->tf_ssr |= PSL_MD;
4061.1Sitojun		return (0);
4071.1Sitojun
4081.1Sitojun	case CPU_DEBUGMODE:
4091.1Sitojun		return (sysctl_int(oldp, oldlenp, newp, newlen,
4101.1Sitojun				   &cpu_debug_mode));
4111.1Sitojun
4121.1Sitojun	case CPU_LOADANDRESET:
4131.1Sitojun		if (newp != NULL) {
4141.1Sitojun			osimage = (char *)(*(u_long *)newp);
4151.1Sitojun
4161.1Sitojun			LoadAndReset(osimage);
4171.1Sitojun			/* not reach here */
4181.1Sitojun		}
4191.1Sitojun		return (0);
4201.1Sitojun
4211.1Sitojun	default:
4221.1Sitojun		return (EOPNOTSUPP);
4231.1Sitojun	}
4241.1Sitojun	/* NOTREACHED */
4251.1Sitojun}
4261.1Sitojun
4271.1Sitojun/*
4281.1Sitojun * Send an interrupt to process.
4291.1Sitojun *
4301.1Sitojun * Stack is set up to allow sigcode stored
4311.1Sitojun * in u. to call routine, followed by kcall
4321.1Sitojun * to sigreturn routine below.  After sigreturn
4331.1Sitojun * resets the signal mask, the stack, and the
4341.1Sitojun * frame pointer, it returns to the user
4351.1Sitojun * specified pc, psl.
4361.1Sitojun */
4371.1Sitojunvoid
4381.1Sitojunsendsig(catcher, sig, mask, code)
4391.1Sitojun	sig_t catcher;
4401.1Sitojun	int sig;
4411.1Sitojun	sigset_t *mask;
4421.1Sitojun	u_long code;
4431.1Sitojun{
4441.1Sitojun	struct proc *p = curproc;
4451.1Sitojun	struct trapframe *tf;
4461.1Sitojun	struct sigframe *fp, frame;
4471.1Sitojun	struct sigacts *psp = p->p_sigacts;
4481.1Sitojun	int onstack;
4491.1Sitojun
4501.1Sitojun	tf = p->p_md.md_regs;
4511.1Sitojun
4521.1Sitojun	/* Do we need to jump onto the signal stack? */
4531.1Sitojun	onstack =
4541.1Sitojun	    (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
4551.1Sitojun	    (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
4561.1Sitojun
4571.1Sitojun	/* Allocate space for the signal handler context. */
4581.1Sitojun	if (onstack)
4591.1Sitojun		fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp +
4601.1Sitojun						  psp->ps_sigstk.ss_size);
4611.1Sitojun	else
4621.1Sitojun		fp = (struct sigframe *)tf->tf_r15;
4631.1Sitojun	fp--;
4641.1Sitojun
4651.1Sitojun	/* Build stack frame for signal trampoline. */
4661.1Sitojun	frame.sf_signum = sig;
4671.1Sitojun	frame.sf_code = code;
4681.1Sitojun	frame.sf_scp = &fp->sf_sc;
4691.1Sitojun	frame.sf_handler = catcher;
4701.1Sitojun
4711.1Sitojun	/* Save register context. */
4721.1Sitojun	frame.sf_sc.sc_ssr = tf->tf_ssr;
4731.1Sitojun	frame.sf_sc.sc_spc = tf->tf_spc;
4741.1Sitojun	frame.sf_sc.sc_pr = tf->tf_pr;
4751.1Sitojun	frame.sf_sc.sc_r15 = tf->tf_r15;
4761.1Sitojun	frame.sf_sc.sc_r14 = tf->tf_r14;
4771.1Sitojun	frame.sf_sc.sc_r13 = tf->tf_r13;
4781.1Sitojun	frame.sf_sc.sc_r12 = tf->tf_r12;
4791.1Sitojun	frame.sf_sc.sc_r11 = tf->tf_r11;
4801.1Sitojun	frame.sf_sc.sc_r10 = tf->tf_r10;
4811.1Sitojun	frame.sf_sc.sc_r9 = tf->tf_r9;
4821.1Sitojun	frame.sf_sc.sc_r8 = tf->tf_r8;
4831.1Sitojun	frame.sf_sc.sc_r7 = tf->tf_r7;
4841.1Sitojun	frame.sf_sc.sc_r6 = tf->tf_r6;
4851.1Sitojun	frame.sf_sc.sc_r5 = tf->tf_r5;
4861.1Sitojun	frame.sf_sc.sc_r4 = tf->tf_r4;
4871.1Sitojun	frame.sf_sc.sc_r3 = tf->tf_r3;
4881.1Sitojun	frame.sf_sc.sc_r2 = tf->tf_r2;
4891.1Sitojun	frame.sf_sc.sc_r1 = tf->tf_r1;
4901.1Sitojun	frame.sf_sc.sc_r0 = tf->tf_r0;
4911.1Sitojun	frame.sf_sc.sc_trapno = tf->tf_trapno;
4921.1Sitojun#ifdef TODO
4931.1Sitojun	frame.sf_sc.sc_err = tf->tf_err;
4941.1Sitojun#endif
4951.1Sitojun
4961.1Sitojun	/* Save signal stack. */
4971.1Sitojun	frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
4981.1Sitojun
4991.1Sitojun	/* Save signal mask. */
5001.1Sitojun	frame.sf_sc.sc_mask = *mask;
5011.1Sitojun
5021.1Sitojun#ifdef COMPAT_13
5031.1Sitojun	/*
5041.1Sitojun	 * XXX We always have to save an old style signal mask because
5051.1Sitojun	 * XXX we might be delivering a signal to a process which will
5061.1Sitojun	 * XXX escape from the signal in a non-standard way and invoke
5071.1Sitojun	 * XXX sigreturn() directly.
5081.1Sitojun	 */
5091.1Sitojun	native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
5101.1Sitojun#endif
5111.1Sitojun
5121.1Sitojun	if (copyout(&frame, fp, sizeof(frame)) != 0) {
5131.1Sitojun		/*
5141.1Sitojun		 * Process has trashed its stack; give it an illegal
5151.1Sitojun		 * instruction to halt it in its tracks.
5161.1Sitojun		 */
5171.1Sitojun		sigexit(p, SIGILL);
5181.1Sitojun		/* NOTREACHED */
5191.1Sitojun	}
5201.1Sitojun
5211.1Sitojun	/*
5221.1Sitojun	 * Build context to run handler in.
5231.1Sitojun	 */
5241.1Sitojun	tf->tf_spc = (int)psp->ps_sigcode;
5251.1Sitojun#ifdef TODO
5261.1Sitojun	tf->tf_ssr &= ~(PSL_T|PSL_VM|PSL_AC);
5271.1Sitojun#endif
5281.1Sitojun	tf->tf_r15 = (int)fp;
5291.1Sitojun
5301.1Sitojun	/* Remember that we're now on the signal stack. */
5311.1Sitojun	if (onstack)
5321.1Sitojun		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
5331.1Sitojun}
5341.1Sitojun
5351.1Sitojun/*
5361.1Sitojun * System call to cleanup state after a signal
5371.1Sitojun * has been taken.  Reset signal mask and
5381.1Sitojun * stack state from context left by sendsig (above).
5391.1Sitojun * Return to previous pc and psl as specified by
5401.1Sitojun * context left by sendsig. Check carefully to
5411.1Sitojun * make sure that the user has not modified the
5421.1Sitojun * psl to gain improper privileges or to cause
5431.1Sitojun * a machine fault.
5441.1Sitojun */
5451.1Sitojunint
5461.1Sitojunsys___sigreturn14(p, v, retval)
5471.1Sitojun	struct proc *p;
5481.1Sitojun	void *v;
5491.1Sitojun	register_t *retval;
5501.1Sitojun{
5511.1Sitojun	struct sys___sigreturn14_args /* {
5521.1Sitojun		syscallarg(struct sigcontext *) sigcntxp;
5531.1Sitojun	} */ *uap = v;
5541.1Sitojun	struct sigcontext *scp, context;
5551.1Sitojun	struct trapframe *tf;
5561.1Sitojun
5571.1Sitojun	/*
5581.1Sitojun	 * The trampoline code hands us the context.
5591.1Sitojun	 * It is unsafe to keep track of it ourselves, in the event that a
5601.1Sitojun	 * program jumps out of a signal handler.
5611.1Sitojun	 */
5621.1Sitojun	scp = SCARG(uap, sigcntxp);
5631.1Sitojun	if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
5641.1Sitojun		return (EFAULT);
5651.1Sitojun
5661.1Sitojun	/* Restore signal context. */
5671.1Sitojun	tf = p->p_md.md_regs;
5681.1Sitojun	{
5691.1Sitojun		/*
5701.1Sitojun		 * Check for security violations.  If we're returning to
5711.1Sitojun		 * protected mode, the CPU will validate the segment registers
5721.1Sitojun		 * automatically and generate a trap on violations.  We handle
5731.1Sitojun		 * the trap, rather than doing all of the checking here.
5741.1Sitojun		 */
5751.1Sitojun#ifdef TODO
5761.1Sitojun	  if (((context.sc_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0) {
5771.1Sitojun	    return (EINVAL);
5781.1Sitojun	  }
5791.1Sitojun#endif
5801.1Sitojun
5811.1Sitojun	  tf->tf_ssr = context.sc_ssr;
5821.1Sitojun	}
5831.1Sitojun	tf->tf_r0 = context.sc_r0;
5841.1Sitojun	tf->tf_r1 = context.sc_r1;
5851.1Sitojun	tf->tf_r2 = context.sc_r2;
5861.1Sitojun	tf->tf_r3 = context.sc_r3;
5871.1Sitojun	tf->tf_r4 = context.sc_r4;
5881.1Sitojun	tf->tf_r5 = context.sc_r5;
5891.1Sitojun	tf->tf_r6 = context.sc_r6;
5901.1Sitojun	tf->tf_r7 = context.sc_r7;
5911.1Sitojun	tf->tf_r8 = context.sc_r8;
5921.1Sitojun	tf->tf_r9 = context.sc_r9;
5931.1Sitojun	tf->tf_r10 = context.sc_r10;
5941.1Sitojun	tf->tf_r11 = context.sc_r11;
5951.1Sitojun	tf->tf_r12 = context.sc_r12;
5961.1Sitojun	tf->tf_r13 = context.sc_r13;
5971.1Sitojun	tf->tf_r14 = context.sc_r14;
5981.1Sitojun	tf->tf_spc = context.sc_spc;
5991.1Sitojun	tf->tf_r15 = context.sc_r15;
6001.1Sitojun	tf->tf_pr = context.sc_pr;
6011.1Sitojun
6021.1Sitojun	/* Restore signal stack. */
6031.1Sitojun	if (context.sc_onstack & SS_ONSTACK)
6041.1Sitojun		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
6051.1Sitojun	else
6061.1Sitojun		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
6071.1Sitojun	/* Restore signal mask. */
6081.1Sitojun	(void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
6091.1Sitojun
6101.1Sitojun	return (EJUSTRETURN);
6111.1Sitojun}
6121.1Sitojun
6131.1Sitojunint	waittime = -1;
6141.1Sitojunstruct pcb dumppcb;
6151.1Sitojun
6161.1Sitojunvoid
6171.1Sitojuncpu_reboot(howto, bootstr)
6181.1Sitojun	int howto;
6191.1Sitojun	char *bootstr;
6201.1Sitojun{
6211.1Sitojun	extern int cold;
6221.1Sitojun
6231.1Sitojun	if (cold) {
6241.1Sitojun		howto |= RB_HALT;
6251.1Sitojun		goto haltsys;
6261.1Sitojun	}
6271.1Sitojun
6281.1Sitojun	boothowto = howto;
6291.1Sitojun	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
6301.1Sitojun		waittime = 0;
6311.1Sitojun		vfs_shutdown();
6321.1Sitojun		/*
6331.1Sitojun		 * If we've been adjusting the clock, the todr
6341.1Sitojun		 * will be out of synch; adjust it now.
6351.1Sitojun		 */
6361.1Sitojun		/* resettodr(); */
6371.1Sitojun	}
6381.1Sitojun
6391.1Sitojun	/* Disable interrupts. */
6401.1Sitojun	splhigh();
6411.1Sitojun
6421.1Sitojun	/* Do a dump if requested. */
6431.1Sitojun	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
6441.1Sitojun		dumpsys();
6451.1Sitojun
6461.1Sitojunhaltsys:
6471.1Sitojun	doshutdownhooks();
6481.1Sitojun
6491.1Sitojun	if (howto & RB_HALT) {
6501.1Sitojun		printf("\n");
6511.1Sitojun		printf("The operating system has halted.\n");
6521.1Sitojun		printf("Please press any key to reboot.\n\n");
6531.1Sitojun		cngetc();
6541.1Sitojun	}
6551.1Sitojun
6561.1Sitojun	printf("rebooting...\n");
6571.1Sitojun	cpu_reset();
6581.1Sitojun	for(;;)
6591.1Sitojun		;
6601.1Sitojun	/*NOTREACHED*/
6611.1Sitojun}
6621.1Sitojun
6631.1Sitojun/*
6641.1Sitojun * These variables are needed by /sbin/savecore
6651.1Sitojun */
6661.1Sitojunu_long	dumpmag = 0x8fca0101;	/* magic number */
6671.1Sitojunint 	dumpsize = 0;		/* pages */
6681.1Sitojunlong	dumplo = 0; 		/* blocks */
6691.1Sitojun
6701.1Sitojun/*
6711.1Sitojun * This is called by main to set dumplo and dumpsize.
6721.1Sitojun * Dumps always skip the first CLBYTES of disk space
6731.1Sitojun * in case there might be a disk label stored there.
6741.1Sitojun * If there is extra space, put dump at the end to
6751.1Sitojun * reduce the chance that swapping trashes it.
6761.1Sitojun */
6771.1Sitojunvoid
6781.1Sitojuncpu_dumpconf()
6791.1Sitojun{
6801.1Sitojun#ifdef	TODO
6811.1Sitojun	int nblks;	/* size of dump area */
6821.1Sitojun	int maj;
6831.1Sitojun
6841.1Sitojun	if (dumpdev == NODEV)
6851.1Sitojun		return;
6861.1Sitojun	maj = major(dumpdev);
6871.1Sitojun	if (maj < 0 || maj >= nblkdev)
6881.1Sitojun		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
6891.1Sitojun	if (bdevsw[maj].d_psize == NULL)
6901.1Sitojun		return;
6911.1Sitojun	nblks = (*bdevsw[maj].d_psize)(dumpdev);
6921.1Sitojun	if (nblks <= ctod(1))
6931.1Sitojun		return;
6941.1Sitojun
6951.1Sitojun	dumpsize = btoc(IOM_END + ctob(dumpmem_high));
6961.1Sitojun
6971.1Sitojun	/* Always skip the first CLBYTES, in case there is a label there. */
6981.1Sitojun	if (dumplo < ctod(1))
6991.1Sitojun		dumplo = ctod(1);
7001.1Sitojun
7011.1Sitojun	/* Put dump at end of partition, and make it fit. */
7021.1Sitojun	if (dumpsize > dtoc(nblks - dumplo))
7031.1Sitojun		dumpsize = dtoc(nblks - dumplo);
7041.1Sitojun	if (dumplo < nblks - ctod(dumpsize))
7051.1Sitojun		dumplo = nblks - ctod(dumpsize);
7061.1Sitojun#endif
7071.1Sitojun}
7081.1Sitojun
7091.1Sitojun/*
7101.1Sitojun * Doadump comes here after turning off memory management and
7111.1Sitojun * getting on the dump stack, either when called above, or by
7121.1Sitojun * the auto-restart code.
7131.1Sitojun */
7141.1Sitojun#define BYTES_PER_DUMP  NBPG	/* must be a multiple of pagesize XXX small */
7151.1Sitojunstatic vaddr_t dumpspace;
7161.1Sitojun
7171.1Sitojunvaddr_t
7181.1Sitojunreserve_dumppages(p)
7191.1Sitojun	vaddr_t p;
7201.1Sitojun{
7211.1Sitojun
7221.1Sitojun	dumpspace = p;
7231.1Sitojun	return (p + BYTES_PER_DUMP);
7241.1Sitojun}
7251.1Sitojun
7261.1Sitojunvoid
7271.1Sitojundumpsys()
7281.1Sitojun{
7291.1Sitojun#ifdef	TODO
7301.1Sitojun	unsigned bytes, i, n;
7311.1Sitojun	int maddr, psize;
7321.1Sitojun	daddr_t blkno;
7331.1Sitojun	int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
7341.1Sitojun	int error;
7351.1Sitojun
7361.1Sitojun	/* Save registers. */
7371.1Sitojun	savectx(&dumppcb);
7381.1Sitojun
7391.1Sitojun	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
7401.1Sitojun	if (dumpdev == NODEV)
7411.1Sitojun		return;
7421.1Sitojun
7431.1Sitojun	/*
7441.1Sitojun	 * For dumps during autoconfiguration,
7451.1Sitojun	 * if dump device has already configured...
7461.1Sitojun	 */
7471.1Sitojun	if (dumpsize == 0)
7481.1Sitojun		cpu_dumpconf();
7491.1Sitojun	if (dumplo < 0)
7501.1Sitojun		return;
7511.1Sitojun	printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
7521.1Sitojun
7531.1Sitojun	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
7541.1Sitojun	printf("dump ");
7551.1Sitojun	if (psize == -1) {
7561.1Sitojun		printf("area unavailable\n");
7571.1Sitojun		return;
7581.1Sitojun	}
7591.1Sitojun
7601.1Sitojun#if 0	/* XXX this doesn't work.  grr. */
7611.1Sitojun        /* toss any characters present prior to dump */
7621.1Sitojun	while (sget() != NULL); /*syscons and pccons differ */
7631.1Sitojun#endif
7641.1Sitojun
7651.1Sitojun	bytes = ctob(dumpmem_high) + IOM_END;
7661.1Sitojun	maddr = 0;
7671.1Sitojun	blkno = dumplo;
7681.1Sitojun	dump = bdevsw[major(dumpdev)].d_dump;
7691.1Sitojun	error = 0;
7701.1Sitojun	for (i = 0; i < bytes; i += n) {
7711.1Sitojun		/*
7721.1Sitojun		 * Avoid dumping the ISA memory hole, and areas that
7731.1Sitojun		 * BIOS claims aren't in low memory.
7741.1Sitojun		 */
7751.1Sitojun		if (i >= ctob(dumpmem_low) && i < IOM_END) {
7761.1Sitojun			n = IOM_END - i;
7771.1Sitojun			maddr += n;
7781.1Sitojun			blkno += btodb(n);
7791.1Sitojun			continue;
7801.1Sitojun		}
7811.1Sitojun
7821.1Sitojun		/* Print out how many MBs we to go. */
7831.1Sitojun		n = bytes - i;
7841.1Sitojun		if (n && (n % (1024*1024)) == 0)
7851.1Sitojun			printf("%d ", n / (1024 * 1024));
7861.1Sitojun
7871.1Sitojun		/* Limit size for next transfer. */
7881.1Sitojun		if (n > BYTES_PER_DUMP)
7891.1Sitojun			n =  BYTES_PER_DUMP;
7901.1Sitojun
7911.1Sitojun		(void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);
7921.1Sitojun		error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
7931.1Sitojun		if (error)
7941.1Sitojun			break;
7951.1Sitojun		maddr += n;
7961.1Sitojun		blkno += btodb(n);			/* XXX? */
7971.1Sitojun
7981.1Sitojun#if 0	/* XXX this doesn't work.  grr. */
7991.1Sitojun		/* operator aborting dump? */
8001.1Sitojun		if (sget() != NULL) {
8011.1Sitojun			error = EINTR;
8021.1Sitojun			break;
8031.1Sitojun		}
8041.1Sitojun#endif
8051.1Sitojun	}
8061.1Sitojun
8071.1Sitojun	switch (error) {
8081.1Sitojun
8091.1Sitojun	case ENXIO:
8101.1Sitojun		printf("device bad\n");
8111.1Sitojun		break;
8121.1Sitojun
8131.1Sitojun	case EFAULT:
8141.1Sitojun		printf("device not ready\n");
8151.1Sitojun		break;
8161.1Sitojun
8171.1Sitojun	case EINVAL:
8181.1Sitojun		printf("area improper\n");
8191.1Sitojun		break;
8201.1Sitojun
8211.1Sitojun	case EIO:
8221.1Sitojun		printf("i/o error\n");
8231.1Sitojun		break;
8241.1Sitojun
8251.1Sitojun	case EINTR:
8261.1Sitojun		printf("aborted from console\n");
8271.1Sitojun		break;
8281.1Sitojun
8291.1Sitojun	case 0:
8301.1Sitojun		printf("succeeded\n");
8311.1Sitojun		break;
8321.1Sitojun
8331.1Sitojun	default:
8341.1Sitojun		printf("error %d\n", error);
8351.1Sitojun		break;
8361.1Sitojun	}
8371.1Sitojun	printf("\n\n");
8381.1Sitojun	delay(5000000);		/* 5 seconds */
8391.1Sitojun#endif	/* TODO */
8401.1Sitojun}
8411.1Sitojun
8421.1Sitojun/*
8431.1Sitojun * Clear registers on exec
8441.1Sitojun */
8451.1Sitojunvoid
8461.1Sitojunsetregs(p, pack, stack)
8471.1Sitojun	struct proc *p;
8481.1Sitojun	struct exec_package *pack;
8491.1Sitojun	u_long stack;
8501.1Sitojun{
8511.1Sitojun	register struct pcb *pcb = &p->p_addr->u_pcb;
8521.1Sitojun	register struct trapframe *tf;
8531.1Sitojun
8541.1Sitojun	p->p_md.md_flags &= ~MDP_USEDFPU;
8551.1Sitojun	pcb->pcb_flags = 0;
8561.1Sitojun
8571.1Sitojun	tf = p->p_md.md_regs;
8581.1Sitojun
8591.1Sitojun	tf->tf_r0 = 0;
8601.1Sitojun	tf->tf_r1 = 0;
8611.1Sitojun	tf->tf_r2 = 0;
8621.1Sitojun	tf->tf_r3 = 0;
8631.1Sitojun	tf->tf_r4 = *(int *)stack;	/* argc */
8641.1Sitojun	tf->tf_r5 = stack+4;		/* argv */
8651.1Sitojun	tf->tf_r6 = stack+4*tf->tf_r4 + 8; /* envp */
8661.1Sitojun	tf->tf_r7 = 0;
8671.1Sitojun	tf->tf_r8 = 0;
8681.1Sitojun	tf->tf_r9 = 0;
8691.1Sitojun	tf->tf_r10 = 0;
8701.1Sitojun	tf->tf_r11 = 0;
8711.1Sitojun	tf->tf_r12 = 0;
8721.1Sitojun	tf->tf_r13 = 0;
8731.1Sitojun	tf->tf_r14 = 0;
8741.1Sitojun	tf->tf_spc = pack->ep_entry;
8751.1Sitojun	tf->tf_ssr = PSL_USERSET;
8761.1Sitojun	tf->tf_r15 = stack;
8771.1Sitojun#ifdef TODO
8781.1Sitojun	tf->tf_ebx = (int)PS_STRINGS;
8791.1Sitojun#endif
8801.1Sitojun}
8811.1Sitojun
8821.1Sitojun/*
8831.1Sitojun * Initialize segments and descriptor tables
8841.1Sitojun */
8851.1Sitojun
8861.1Sitojunextern  struct user *proc0paddr;
8871.1Sitojun
8881.1Sitojunvoid
8891.1SitojuninitSH3(first_avail)
8901.1Sitojun	vaddr_t first_avail;
8911.1Sitojun{
8921.1Sitojun	unsigned short *p;
8931.1Sitojun	unsigned short sum;
8941.1Sitojun	int	size;
8951.1Sitojun	extern void consinit __P((void));
8961.1Sitojun
8971.1Sitojun	proc0.p_addr = proc0paddr; /* page dir address */
8981.1Sitojun
8991.1Sitojun	/*
9001.1Sitojun	 * Initialize the I/O port and I/O mem extent maps.
9011.1Sitojun	 * Note: we don't have to check the return value since
9021.1Sitojun	 * creation of a fixed extent map will never fail (since
9031.1Sitojun	 * descriptor storage has already been allocated).
9041.1Sitojun	 *
9051.1Sitojun	 * N.B. The iomem extent manages _all_ physical addresses
9061.1Sitojun	 * on the machine.  When the amount of RAM is found, the two
9071.1Sitojun	 * extents of RAM are allocated from the map (0 -> ISA hole
9081.1Sitojun	 * and end of ISA hole -> end of RAM).
9091.1Sitojun	 */
9101.1Sitojun	iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
9111.1Sitojun	    (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
9121.1Sitojun	    EX_NOCOALESCE|EX_NOWAIT);
9131.1Sitojun
9141.1Sitojun#if 0	/* XXX (msaitoh) */
9151.1Sitojun	consinit();	/* XXX SHOULD NOT BE DONE HERE */
9161.1Sitojun#endif
9171.1Sitojun
9181.1Sitojun	splraise(-1);
9191.1Sitojun	enable_intr();
9201.1Sitojun
9211.1Sitojun	avail_end = sh3_trunc_page(IOM_RAM_END + 1);
9221.1Sitojun
9231.1Sitojun#if 0	/* XXX (msaitoh) */
9241.1Sitojun	printf("initSH3\r\n");
9251.1Sitojun#endif
9261.1Sitojun
9271.1Sitojun	/*
9281.1Sitojun	 * Calculate check sum
9291.1Sitojun	 */
9301.1Sitojun	size = (char *)&etext - (char *)&_start;
9311.1Sitojun	p = (unsigned short *)&_start;
9321.1Sitojun	sum = 0;
9331.1Sitojun	size >>= 1;
9341.1Sitojun	while (size--)
9351.1Sitojun		sum += *p++;
9361.1Sitojun#if 0
9371.1Sitojun	printf("Check Sum = 0x%x", sum);
9381.1Sitojun#endif
9391.1Sitojun
9401.1Sitojun	/*
9411.1Sitojun	 * Allocate the physical addresses used by RAM from the iomem
9421.1Sitojun	 * extent map.  This is done before the addresses are
9431.1Sitojun	 * page rounded just to make sure we get them all.
9441.1Sitojun	 */
9451.1Sitojun	if (extent_alloc_region(iomem_ex, IOM_RAM_BEGIN,
9461.1Sitojun				IOM_RAM_SIZE,
9471.1Sitojun				EX_NOWAIT)) {
9481.1Sitojun		/* XXX What should we do? */
9491.1Sitojun#if 1
9501.1Sitojun		printf("WARNING: CAN'T ALLOCATE RAM MEMORY FROM IOMEM EXTENT MAP!\n");
9511.1Sitojun#endif
9521.1Sitojun	}
9531.1Sitojun
9541.1Sitojun#if 0 /* avail_start is set in locore.s to first available page rounded
9551.1Sitojun	 physical mem */
9561.1Sitojun	avail_start = IOM_RAM_BEGIN + NBPG;
9571.1Sitojun#endif
9581.1Sitojun
9591.1Sitojun	/* number of pages of physmem addr space */
9601.1Sitojun	physmem = btoc(IOM_RAM_SIZE);
9611.1Sitojun#ifdef	TODO
9621.1Sitojun	dumpmem = physmem;
9631.1Sitojun#endif
9641.1Sitojun
9651.1Sitojun	/*
9661.1Sitojun	 * Initialize for pmap_free_pages and pmap_next_page.
9671.1Sitojun	 * These guys should be page-aligned.
9681.1Sitojun	 */
9691.1Sitojun	if (physmem < btoc(2 * 1024 * 1024)) {
9701.1Sitojun		printf("warning: too little memory available; "
9711.1Sitojun		       "have %d bytes, want %d bytes\n"
9721.1Sitojun		       "running in degraded mode\n"
9731.1Sitojun		       "press a key to confirm\n\n",
9741.1Sitojun		       ctob(physmem), 2*1024*1024);
9751.1Sitojun		cngetc();
9761.1Sitojun	}
9771.1Sitojun
9781.1Sitojun	/* Call pmap initialization to make new kernel address space */
9791.1Sitojun	pmap_bootstrap((vaddr_t)atdevbase);
9801.1Sitojun
9811.1Sitojun	/*
9821.1Sitojun	 * Initialize error message buffer (at end of core).
9831.1Sitojun	 */
9841.1Sitojun	initmsgbuf((caddr_t)msgbuf_paddr, round_page(MSGBUFSIZE));
9851.1Sitojun
9861.1Sitojun	/*
9871.1Sitojun	 * set boot device information
9881.1Sitojun	 */
9891.1Sitojun	setup_bootinfo();
9901.1Sitojun
9911.1Sitojun#if 0
9921.1Sitojun	sh3_cache_on();
9931.1Sitojun#endif
9941.1Sitojun
9951.1Sitojun}
9961.1Sitojun
9971.1Sitojunstruct queue {
9981.1Sitojun	struct queue *q_next, *q_prev;
9991.1Sitojun};
10001.1Sitojun
10011.1Sitojun/*
10021.1Sitojun * insert an element into a queue
10031.1Sitojun */
10041.1Sitojunvoid
10051.1Sitojun_insque(v1, v2)
10061.1Sitojun	void *v1;
10071.1Sitojun	void *v2;
10081.1Sitojun{
10091.1Sitojun	struct queue *elem = v1, *head = v2;
10101.1Sitojun	struct queue *next;
10111.1Sitojun
10121.1Sitojun	next = head->q_next;
10131.1Sitojun	elem->q_next = next;
10141.1Sitojun	head->q_next = elem;
10151.1Sitojun	elem->q_prev = head;
10161.1Sitojun	next->q_prev = elem;
10171.1Sitojun}
10181.1Sitojun
10191.1Sitojun/*
10201.1Sitojun * remove an element from a queue
10211.1Sitojun */
10221.1Sitojunvoid
10231.1Sitojun_remque(v)
10241.1Sitojun	void *v;
10251.1Sitojun{
10261.1Sitojun	struct queue *elem = v;
10271.1Sitojun	struct queue *next, *prev;
10281.1Sitojun
10291.1Sitojun	next = elem->q_next;
10301.1Sitojun	prev = elem->q_prev;
10311.1Sitojun	next->q_prev = prev;
10321.1Sitojun	prev->q_next = next;
10331.1Sitojun	elem->q_prev = 0;
10341.1Sitojun}
10351.1Sitojun
10361.1Sitojun#ifdef COMPAT_NOMID
10371.1Sitojunstatic int
10381.1Sitojunexec_nomid(p, epp)
10391.1Sitojun	struct proc *p;
10401.1Sitojun	struct exec_package *epp;
10411.1Sitojun{
10421.1Sitojun	int error;
10431.1Sitojun	u_long midmag, magic;
10441.1Sitojun	u_short mid;
10451.1Sitojun	struct exec *execp = epp->ep_hdr;
10461.1Sitojun
10471.1Sitojun	/* check on validity of epp->ep_hdr performed by exec_out_makecmds */
10481.1Sitojun
10491.1Sitojun	midmag = ntohl(execp->a_midmag);
10501.1Sitojun	mid = (midmag >> 16) & 0xffff;
10511.1Sitojun	magic = midmag & 0xffff;
10521.1Sitojun
10531.1Sitojun	if (magic == 0) {
10541.1Sitojun		magic = (execp->a_midmag & 0xffff);
10551.1Sitojun		mid = MID_ZERO;
10561.1Sitojun	}
10571.1Sitojun
10581.1Sitojun	midmag = mid << 16 | magic;
10591.1Sitojun
10601.1Sitojun	switch (midmag) {
10611.1Sitojun	case (MID_ZERO << 16) | ZMAGIC:
10621.1Sitojun		/*
10631.1Sitojun		 * 386BSD's ZMAGIC format:
10641.1Sitojun		 */
10651.1Sitojun		error = exec_aout_prep_oldzmagic(p, epp);
10661.1Sitojun		break;
10671.1Sitojun
10681.1Sitojun	case (MID_ZERO << 16) | QMAGIC:
10691.1Sitojun		/*
10701.1Sitojun		 * BSDI's QMAGIC format:
10711.1Sitojun		 * same as new ZMAGIC format, but with different magic number
10721.1Sitojun		 */
10731.1Sitojun		error = exec_aout_prep_zmagic(p, epp);
10741.1Sitojun		break;
10751.1Sitojun
10761.1Sitojun	case (MID_ZERO << 16) | NMAGIC:
10771.1Sitojun		/*
10781.1Sitojun		 * BSDI's NMAGIC format:
10791.1Sitojun		 * same as NMAGIC format, but with different magic number
10801.1Sitojun		 * and with text starting at 0.
10811.1Sitojun		 */
10821.1Sitojun		error = exec_aout_prep_oldnmagic(p, epp);
10831.1Sitojun		break;
10841.1Sitojun
10851.1Sitojun	case (MID_ZERO << 16) | OMAGIC:
10861.1Sitojun		/*
10871.1Sitojun		 * BSDI's OMAGIC format:
10881.1Sitojun		 * same as OMAGIC format, but with different magic number
10891.1Sitojun		 * and with text starting at 0.
10901.1Sitojun		 */
10911.1Sitojun		error = exec_aout_prep_oldomagic(p, epp);
10921.1Sitojun		break;
10931.1Sitojun
10941.1Sitojun	default:
10951.1Sitojun		error = ENOEXEC;
10961.1Sitojun	}
10971.1Sitojun
10981.1Sitojun	return error;
10991.1Sitojun}
11001.1Sitojun#endif
11011.1Sitojun
11021.1Sitojun/*
11031.1Sitojun * cpu_exec_aout_makecmds():
11041.1Sitojun *	cpu-dependent a.out format hook for execve().
11051.1Sitojun *
11061.1Sitojun * Determine of the given exec package refers to something which we
11071.1Sitojun * understand and, if so, set up the vmcmds for it.
11081.1Sitojun *
11091.1Sitojun * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
11101.1Sitojun * if COMPAT_NOMID is given as a kernel option.
11111.1Sitojun */
11121.1Sitojunint
11131.1Sitojuncpu_exec_aout_makecmds(p, epp)
11141.1Sitojun	struct proc *p;
11151.1Sitojun	struct exec_package *epp;
11161.1Sitojun{
11171.1Sitojun	int error = ENOEXEC;
11181.1Sitojun
11191.1Sitojun#ifdef COMPAT_NOMID
11201.1Sitojun	if ((error = exec_nomid(p, epp)) == 0)
11211.1Sitojun		return error;
11221.1Sitojun#endif /* ! COMPAT_NOMID */
11231.1Sitojun
11241.1Sitojun	return error;
11251.1Sitojun}
11261.1Sitojun
11271.1Sitojunvoid
11281.1Sitojunsetup_bootinfo(void)
11291.1Sitojun{
11301.1Sitojun	struct btinfo_bootdisk *help;
11311.1Sitojun
11321.1Sitojun	*(int *)bootinfo = 1;
11331.1Sitojun	help = (struct btinfo_bootdisk *)(bootinfo + sizeof(int));
11341.1Sitojun	help->biosdev = 0;
11351.1Sitojun	help->partition = 0;
11361.1Sitojun	((struct btinfo_common *)help)->len = sizeof(struct btinfo_bootdisk);
11371.1Sitojun	((struct btinfo_common *)help)->type = BTINFO_BOOTDISK;
11381.1Sitojun}
11391.1Sitojun
11401.1Sitojunvoid *
11411.1Sitojunlookup_bootinfo(type)
11421.1Sitojun	int type;
11431.1Sitojun{
11441.1Sitojun	struct btinfo_common *help;
11451.1Sitojun	int n = *(int*)bootinfo;
11461.1Sitojun	help = (struct btinfo_common *)(bootinfo + sizeof(int));
11471.1Sitojun	while (n--) {
11481.1Sitojun		if (help->type == type)
11491.1Sitojun			return (help);
11501.1Sitojun		help = (struct btinfo_common *)((char*)help + help->len);
11511.1Sitojun	}
11521.1Sitojun	return (0);
11531.1Sitojun}
11541.1Sitojun
11551.1Sitojun
11561.1Sitojun/*
11571.1Sitojun * consinit:
11581.1Sitojun * initialize the system console.
11591.1Sitojun * XXX - shouldn't deal with this initted thing, but then,
11601.1Sitojun * it shouldn't be called from init386 either.
11611.1Sitojun */
11621.1Sitojunvoid
11631.1Sitojunconsinit()
11641.1Sitojun{
11651.1Sitojun	static int initted;
11661.1Sitojun
11671.1Sitojun	if (initted)
11681.1Sitojun		return;
11691.1Sitojun	initted = 1;
11701.1Sitojun
11711.1Sitojun	cninit();
11721.1Sitojun
11731.1Sitojun#ifdef DDB
11741.1Sitojun	ddb_init();
11751.1Sitojun#endif
11761.1Sitojun}
11771.1Sitojun
11781.1Sitojunvoid
11791.1Sitojuncpu_reset()
11801.1Sitojun{
11811.1Sitojun
11821.1Sitojun	disable_intr();
11831.1Sitojun
11841.1Sitojun	Sh3Reset();
11851.1Sitojun	for (;;)
11861.1Sitojun		;
11871.1Sitojun}
11881.1Sitojun
11891.1Sitojunint
11901.1Sitojunbus_space_map (t, addr, size, flags, bshp)
11911.1Sitojun	bus_space_tag_t t;
11921.1Sitojun	bus_addr_t addr;
11931.1Sitojun	bus_size_t size;
11941.1Sitojun	int flags;
11951.1Sitojun	bus_space_handle_t *bshp;
11961.1Sitojun{
11971.1Sitojun
11981.1Sitojun	*bshp = (bus_space_handle_t)addr;
11991.1Sitojun
12001.1Sitojun	return 0;
12011.1Sitojun}
12021.1Sitojun
12031.1Sitojunint
12041.1Sitojunsh_memio_subregion(t, bsh, offset, size, nbshp)
12051.1Sitojun	bus_space_tag_t t;
12061.1Sitojun	bus_space_handle_t bsh;
12071.1Sitojun	bus_size_t offset, size;
12081.1Sitojun	bus_space_handle_t *nbshp;
12091.1Sitojun{
12101.1Sitojun
12111.1Sitojun	*nbshp = bsh + offset;
12121.1Sitojun	return (0);
12131.1Sitojun}
12141.1Sitojun
12151.1Sitojunint
12161.1Sitojunsh_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
12171.1Sitojun	       bpap, bshp)
12181.1Sitojun	bus_space_tag_t t;
12191.1Sitojun	bus_addr_t rstart, rend;
12201.1Sitojun	bus_size_t size, alignment, boundary;
12211.1Sitojun	int flags;
12221.1Sitojun	bus_addr_t *bpap;
12231.1Sitojun	bus_space_handle_t *bshp;
12241.1Sitojun{
12251.1Sitojun	*bshp = *bpap = rstart;
12261.1Sitojun
12271.1Sitojun	return (0);
12281.1Sitojun}
12291.1Sitojun
12301.1Sitojunvoid
12311.1Sitojunsh_memio_free(t, bsh, size)
12321.1Sitojun	bus_space_tag_t t;
12331.1Sitojun	bus_space_handle_t bsh;
12341.1Sitojun	bus_size_t size;
12351.1Sitojun{
12361.1Sitojun
12371.1Sitojun}
12381.1Sitojun
12391.1Sitojunvoid
12401.1Sitojunsh_memio_unmap(t, bsh, size)
12411.1Sitojun	bus_space_tag_t t;
12421.1Sitojun	bus_space_handle_t bsh;
12431.1Sitojun	bus_size_t size;
12441.1Sitojun{
12451.1Sitojun	return;
12461.1Sitojun}
12471.1Sitojun
12481.1Sitojun/*
12491.1Sitojun * InitializeBsc
12501.1Sitojun * : BSC(Bus State Controler)
12511.1Sitojun */
12521.1Sitojunvoid InitializeBsc __P((void));
12531.1Sitojun
12541.1Sitojunvoid
12551.1SitojunInitializeBsc()
12561.1Sitojun{
12571.1Sitojun
12581.1Sitojun	/*
12591.1Sitojun	 * Drive RAS,CAS in stand by mode and bus release mode
12601.1Sitojun	 * Area0 = Normal memory, Area5,6=Normal(no burst)
12611.1Sitojun	 * Area2 = Normal memory, Area3 = SDRAM, Area5 = Normal memory
12621.1Sitojun	 * Area4 = Normal Memory
12631.1Sitojun	 * Area6 = Normal memory
12641.1Sitojun	 */
12651.1Sitojun	SHREG_BSC.BCR1.WORD = BSC_BCR1_VAL;
12661.1Sitojun
12671.1Sitojun	/*
12681.1Sitojun	 * Bus Width
12691.1Sitojun	 * Area4: Bus width = 16bit
12701.1Sitojun	 * Area6,5 = 16bit
12711.1Sitojun	 * Area1 = 8bit
12721.1Sitojun	 * Area2,3: Bus width = 32bit
12731.1Sitojun	 */
12741.1Sitojun	 SHREG_BSC.BCR2.WORD = BSC_BCR2_VAL;
12751.1Sitojun
12761.1Sitojun	/*
12771.1Sitojun	 * Idle cycle number in transition area and read to write
12781.1Sitojun	 * Area6 = 3, Area5 = 3, Area4 = 3, Area3 = 3, Area2 = 3
12791.1Sitojun	 * Area1 = 3, Area0 = 3
12801.1Sitojun	 */
12811.1Sitojun	SHREG_BSC.WCR1.WORD = BSC_WCR1_VAL;
12821.1Sitojun
12831.1Sitojun	/*
12841.1Sitojun	 * Wait cycle
12851.1Sitojun	 * Area 6 = 6
12861.1Sitojun	 * Area 5 = 2
12871.1Sitojun	 * Area 4 = 10
12881.1Sitojun	 * Area 3 = 3
12891.1Sitojun	 * Area 2,1 = 3
12901.1Sitojun	 * Area 0 = 6
12911.1Sitojun	 */
12921.1Sitojun	SHREG_BSC.WCR2.WORD = BSC_WCR2_VAL;
12931.1Sitojun
12941.1Sitojun#ifdef SH4
12951.1Sitojun	SHREG_BSC.WCR3.WORD = BSC_WCR3_VAL;
12961.1Sitojun#endif
12971.1Sitojun
12981.1Sitojun	/*
12991.1Sitojun	 * RAS pre-charge = 2cycle, RAS-CAS delay = 3 cycle,
13001.1Sitojun	 * write pre-charge=1cycle
13011.1Sitojun	 * CAS before RAS refresh RAS assert time = 3 cycle
13021.1Sitojun	 * Disable burst, Bus size=32bit, Column Address=10bit, Refresh ON
13031.1Sitojun	 * CAS before RAS refresh ON, EDO DRAM
13041.1Sitojun	 */
13051.1Sitojun	SHREG_BSC.MCR.WORD = BSC_MCR_VAL;
13061.1Sitojun
13071.1Sitojun#ifdef BSC_SDMR_VAL
13081.1Sitojun#if 1
13091.1Sitojun#define SDMR	(*(volatile unsigned char  *)BSC_SDMR_VAL)
13101.1Sitojun
13111.1Sitojun	SDMR = 0;
13121.1Sitojun#else
13131.1Sitojun#define ADDSET	(*(volatile unsigned short *)0x1A000000)
13141.1Sitojun#define ADDRST	(*(volatile unsigned short *)0x18000000)
13151.1Sitojun#define SDMR	(*(volatile unsigned char  *)BSC_SDMR_VAL)
13161.1Sitojun
13171.1Sitojun	ADDSET = 0;
13181.1Sitojun	SDMR = 0;
13191.1Sitojun	ADDRST = 0;
13201.1Sitojun#endif
13211.1Sitojun#endif
13221.1Sitojun
13231.1Sitojun	/*
13241.1Sitojun	 * PCMCIA Control Register
13251.1Sitojun	 * OE/WE assert delay 3.5 cycle
13261.1Sitojun	 * OE/WE negate-address delay 3.5 cycle
13271.1Sitojun	 */
13281.1Sitojun#ifdef BSC_PCR_VAL
13291.1Sitojun	SHREG_BSC.PCR.WORD = 0x00ff;
13301.1Sitojun#endif
13311.1Sitojun
13321.1Sitojun	/*
13331.1Sitojun	 * Refresh Timer Control/Status Register
13341.1Sitojun	 * Disable interrupt by CMF, closk 1/16, Disable OVF interrupt
13351.1Sitojun	 * Count Limit = 1024
13361.1Sitojun	 * In following statement, the reason why high byte = 0xa5(a4 in RFCR)
13371.1Sitojun	 * is the rule of SH3 in writing these register.
13381.1Sitojun	 */
13391.1Sitojun	SHREG_BSC.RTCSR.WORD = BSC_RTCSR_VAL;
13401.1Sitojun
13411.1Sitojun
13421.1Sitojun	/*
13431.1Sitojun	 * Refresh Timer Counter
13441.1Sitojun	 * Initialize to 0
13451.1Sitojun	 */
13461.1Sitojun	SHREG_BSC.RTCNT = BSC_RTCNT_VAL;
13471.1Sitojun
13481.1Sitojun	/* set Refresh Time Constant Register */
13491.1Sitojun	SHREG_BSC.RTCOR = BSC_RTCOR_VAL;
13501.1Sitojun
13511.1Sitojun	/* init Refresh Count Register */
13521.1Sitojun#ifdef BSC_RFCR_VAL
13531.1Sitojun	SHREG_BSC.RFCR = BSC_RFCR_VAL;
13541.1Sitojun#endif
13551.1Sitojun
13561.1Sitojun	/* Set Clock mode (make internal clock double speed) */
13571.1Sitojun
13581.1Sitojun	SHREG_FRQCR = FRQCR_VAL;
13591.1Sitojun
13601.1Sitojun#ifndef MMEYE_NO_CACHE
13611.1Sitojun	/* Cache ON */
13621.1Sitojun	SHREG_CCR = 0x0001;
13631.1Sitojun#endif
13641.1Sitojun}
13651.1Sitojun
13661.1Sitojunvoid
13671.1Sitojunsh3_cache_on(void)
13681.1Sitojun{
13691.1Sitojun#ifndef MMEYE_NO_CACHE
13701.1Sitojun	/* Cache ON */
13711.1Sitojun	SHREG_CCR = 0x0001;
13721.1Sitojun	SHREG_CCR = 0x0009; /* cache clear */
13731.1Sitojun	SHREG_CCR = 0x0001; /* cache on */
13741.1Sitojun#endif
13751.1Sitojun}
13761.1Sitojun
13771.1Sitojun#include <machine/mmeye.h>
13781.1Sitojunvoid
13791.1SitojunLoadAndReset(char *osimage)
13801.1Sitojun{
13811.1Sitojun	void *buf_addr;
13821.1Sitojun	u_long size;
13831.1Sitojun	u_long *src;
13841.1Sitojun	u_long *dest;
13851.1Sitojun	u_long csum = 0;
13861.1Sitojun	u_long csum2 = 0;
13871.1Sitojun	u_long size2;
13881.1Sitojun#define OSIMAGE_BUF_ADDR 0x8c400000 /* !!!!!! This value depends on physical
13891.1Sitojun				       available memory */
13901.1Sitojun
13911.1Sitojun
13921.1Sitojun	printf("LoadAndReset:copy start\n");
13931.1Sitojun	buf_addr = (void *)OSIMAGE_BUF_ADDR;
13941.1Sitojun
13951.1Sitojun	size = *(u_long *)osimage;
13961.1Sitojun	src = (u_long *)osimage;
13971.1Sitojun	dest = buf_addr;
13981.1Sitojun
13991.1Sitojun	size = (size + sizeof(u_long)*2 + 3) >> 2 ;
14001.1Sitojun	size2 = size;
14011.1Sitojun
14021.1Sitojun	while (size--){
14031.1Sitojun		csum += *src;
14041.1Sitojun		*dest++ = *src++;
14051.1Sitojun	}
14061.1Sitojun
14071.1Sitojun	dest = buf_addr;
14081.1Sitojun	while (size2--)
14091.1Sitojun		csum2 += *dest++;
14101.1Sitojun
14111.1Sitojun	printf("LoadAndReset:copy end[%lx,%lx]\n", csum, csum2);
14121.1Sitojun	printf("start XLoadAndReset\n");
14131.1Sitojun
14141.1Sitojun	/* mask all externel interrupt (XXX) */
14151.1Sitojun
14161.1Sitojun	XLoadAndReset(buf_addr);
14171.1Sitojun}
1418