xref: /plan9-contrib/sys/src/9/loongson/2f/main.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
1*a81c3ea0SDavid du Colombier #include "u.h"
2*a81c3ea0SDavid du Colombier #include "../port/lib.h"
3*a81c3ea0SDavid du Colombier #include "mem.h"
4*a81c3ea0SDavid du Colombier #include "dat.h"
5*a81c3ea0SDavid du Colombier #include "fns.h"
6*a81c3ea0SDavid du Colombier #include "io.h"
7*a81c3ea0SDavid du Colombier #include "../ip/ip.h"
8*a81c3ea0SDavid du Colombier #include <pool.h>
9*a81c3ea0SDavid du Colombier #include <tos.h>
10*a81c3ea0SDavid du Colombier #include <bootexec.h>
11*a81c3ea0SDavid du Colombier #include "init.h"
12*a81c3ea0SDavid du Colombier #include "reboot.h"
13*a81c3ea0SDavid du Colombier 
14*a81c3ea0SDavid du Colombier enum {
15*a81c3ea0SDavid du Colombier 	/* space for syscall args, return PC, top-of-stack struct */
16*a81c3ea0SDavid du Colombier 	Stkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
17*a81c3ea0SDavid du Colombier };
18*a81c3ea0SDavid du Colombier 
19*a81c3ea0SDavid du Colombier typedef struct mipsexec Mipsexec;
20*a81c3ea0SDavid du Colombier 
21*a81c3ea0SDavid du Colombier #define	MAXCONF		64
22*a81c3ea0SDavid du Colombier #define CONFBUFLEN	4096
23*a81c3ea0SDavid du Colombier #define MAXBOOTENV	256
24*a81c3ea0SDavid du Colombier 
25*a81c3ea0SDavid du Colombier /* only for reboot */
26*a81c3ea0SDavid du Colombier #define BOOTARGS	((char*)(CONFADDR))
27*a81c3ea0SDavid du Colombier #define BOOTARGSLEN	CONFBUFLEN
28*a81c3ea0SDavid du Colombier #define CONFARGVLEN	(MAXCONF*BY2WD)
29*a81c3ea0SDavid du Colombier 
30*a81c3ea0SDavid du Colombier /* args passed by boot loader for main() */
31*a81c3ea0SDavid du Colombier int		_argc;
32*a81c3ea0SDavid du Colombier char	**_argv;
33*a81c3ea0SDavid du Colombier char	**_env;
34*a81c3ea0SDavid du Colombier static char *bootenvname[MAXBOOTENV];
35*a81c3ea0SDavid du Colombier static char *bootenvval[MAXBOOTENV];
36*a81c3ea0SDavid du Colombier static int 	nenv;
37*a81c3ea0SDavid du Colombier 
38*a81c3ea0SDavid du Colombier /* plan9.ini */
39*a81c3ea0SDavid du Colombier static char confbuf[CONFBUFLEN];
40*a81c3ea0SDavid du Colombier static char *confname[MAXCONF];
41*a81c3ea0SDavid du Colombier static char *confval[MAXCONF];
42*a81c3ea0SDavid du Colombier static int	nconf;
43*a81c3ea0SDavid du Colombier 
44*a81c3ea0SDavid du Colombier /*
45*a81c3ea0SDavid du Colombier  * Option arguments from the command line.
46*a81c3ea0SDavid du Colombier  * oargv[0] is the boot file.
47*a81c3ea0SDavid du Colombier  */
48*a81c3ea0SDavid du Colombier static int oargc;
49*a81c3ea0SDavid du Colombier static char* oargv[20];
50*a81c3ea0SDavid du Colombier static char oargb[128];
51*a81c3ea0SDavid du Colombier static int oargblen;
52*a81c3ea0SDavid du Colombier 
53*a81c3ea0SDavid du Colombier static uintptr sp;		/* XXX - must go - user stack of init proc */
54*a81c3ea0SDavid du Colombier 
55*a81c3ea0SDavid du Colombier /*
56*a81c3ea0SDavid du Colombier  * software tlb simulation
57*a81c3ea0SDavid du Colombier  */
58*a81c3ea0SDavid du Colombier static Softtlb stlb[MAXMACH][STLBSIZE];
59*a81c3ea0SDavid du Colombier 
60*a81c3ea0SDavid du Colombier Mach	*machaddr[MAXMACH];
61*a81c3ea0SDavid du Colombier Conf	conf;
62*a81c3ea0SDavid du Colombier ulong	memsize;
63*a81c3ea0SDavid du Colombier FPsave	initfp;
64*a81c3ea0SDavid du Colombier 
65*a81c3ea0SDavid du Colombier int normalprint;
66*a81c3ea0SDavid du Colombier ulong cpufreq;
67*a81c3ea0SDavid du Colombier 
68*a81c3ea0SDavid du Colombier /*
69*a81c3ea0SDavid du Colombier  *  initialize a processor's mach structure.  each processor does this
70*a81c3ea0SDavid du Colombier  *  for itself.
71*a81c3ea0SDavid du Colombier  */
72*a81c3ea0SDavid du Colombier void
machinit(void)73*a81c3ea0SDavid du Colombier machinit(void)
74*a81c3ea0SDavid du Colombier {
75*a81c3ea0SDavid du Colombier 	/* Ensure CU1 is off */
76*a81c3ea0SDavid du Colombier 	clrfpintr();
77*a81c3ea0SDavid du Colombier 
78*a81c3ea0SDavid du Colombier 	m->stb = &stlb[m->machno][0];
79*a81c3ea0SDavid du Colombier 
80*a81c3ea0SDavid du Colombier 	clockinit();
81*a81c3ea0SDavid du Colombier }
82*a81c3ea0SDavid du Colombier 
83*a81c3ea0SDavid du Colombier static void
optionsinit(char * s)84*a81c3ea0SDavid du Colombier optionsinit(char* s)
85*a81c3ea0SDavid du Colombier {
86*a81c3ea0SDavid du Colombier 	strecpy(oargb, oargb+sizeof(oargb), s);
87*a81c3ea0SDavid du Colombier 
88*a81c3ea0SDavid du Colombier 	oargblen = strlen(oargb);
89*a81c3ea0SDavid du Colombier 	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
90*a81c3ea0SDavid du Colombier 	oargv[oargc] = nil;
91*a81c3ea0SDavid du Colombier }
92*a81c3ea0SDavid du Colombier 
93*a81c3ea0SDavid du Colombier void
plan9iniinit(void)94*a81c3ea0SDavid du Colombier plan9iniinit(void)
95*a81c3ea0SDavid du Colombier {
96*a81c3ea0SDavid du Colombier 	char *cp;
97*a81c3ea0SDavid du Colombier 	int i;
98*a81c3ea0SDavid du Colombier 
99*a81c3ea0SDavid du Colombier 	nconf = 0;
100*a81c3ea0SDavid du Colombier 	if(_argv != nil){
101*a81c3ea0SDavid du Colombier 		memmove(confbuf, _argv[0], sizeof(confbuf));
102*a81c3ea0SDavid du Colombier 		for(i=1; i<_argc && nconf<MAXCONF; i++){
103*a81c3ea0SDavid du Colombier 			_argv[i] += confbuf - _argv[0];
104*a81c3ea0SDavid du Colombier 			if(*_argv[i] == '#')
105*a81c3ea0SDavid du Colombier 				continue;
106*a81c3ea0SDavid du Colombier 			cp = strchr(_argv[i], '=');
107*a81c3ea0SDavid du Colombier 			if(cp == nil)
108*a81c3ea0SDavid du Colombier 				continue;
109*a81c3ea0SDavid du Colombier 			*cp++ = '\0';
110*a81c3ea0SDavid du Colombier 			confname[nconf] = _argv[i];
111*a81c3ea0SDavid du Colombier 			confval[nconf] = cp;
112*a81c3ea0SDavid du Colombier 			nconf++;
113*a81c3ea0SDavid du Colombier 		}
114*a81c3ea0SDavid du Colombier 	}
115*a81c3ea0SDavid du Colombier 
116*a81c3ea0SDavid du Colombier 	nenv = 0;
117*a81c3ea0SDavid du Colombier 	if(_env != nil)
118*a81c3ea0SDavid du Colombier 		for(i=0; _env[i] != nil && nenv<MAXBOOTENV; i++){
119*a81c3ea0SDavid du Colombier 			if(*_env[i] == '#')
120*a81c3ea0SDavid du Colombier 				continue;
121*a81c3ea0SDavid du Colombier 			cp = strchr(_env[i], '=');
122*a81c3ea0SDavid du Colombier 			if(cp == nil)
123*a81c3ea0SDavid du Colombier 				continue;
124*a81c3ea0SDavid du Colombier 			*cp++ = '\0';
125*a81c3ea0SDavid du Colombier 			bootenvname[nenv] = _env[i];
126*a81c3ea0SDavid du Colombier 			bootenvval[nenv] = cp;
127*a81c3ea0SDavid du Colombier 			nenv++;
128*a81c3ea0SDavid du Colombier 		}
129*a81c3ea0SDavid du Colombier }
130*a81c3ea0SDavid du Colombier 
131*a81c3ea0SDavid du Colombier static int
findconf(char * name)132*a81c3ea0SDavid du Colombier findconf(char *name)
133*a81c3ea0SDavid du Colombier {
134*a81c3ea0SDavid du Colombier 	int i;
135*a81c3ea0SDavid du Colombier 
136*a81c3ea0SDavid du Colombier 	for(i = 0; i < nconf; i++)
137*a81c3ea0SDavid du Colombier 		if(cistrcmp(confname[i], name) == 0)
138*a81c3ea0SDavid du Colombier 			return i;
139*a81c3ea0SDavid du Colombier 	return -1;
140*a81c3ea0SDavid du Colombier }
141*a81c3ea0SDavid du Colombier 
142*a81c3ea0SDavid du Colombier char*
getconf(char * name)143*a81c3ea0SDavid du Colombier getconf(char *name)
144*a81c3ea0SDavid du Colombier {
145*a81c3ea0SDavid du Colombier 	int i;
146*a81c3ea0SDavid du Colombier 
147*a81c3ea0SDavid du Colombier 	i = findconf(name);
148*a81c3ea0SDavid du Colombier 	if(i >= 0)
149*a81c3ea0SDavid du Colombier 		return confval[i];
150*a81c3ea0SDavid du Colombier 	return nil;
151*a81c3ea0SDavid du Colombier }
152*a81c3ea0SDavid du Colombier 
153*a81c3ea0SDavid du Colombier static int
findbootenv(char * name)154*a81c3ea0SDavid du Colombier findbootenv(char *name)
155*a81c3ea0SDavid du Colombier {
156*a81c3ea0SDavid du Colombier 	int i;
157*a81c3ea0SDavid du Colombier 
158*a81c3ea0SDavid du Colombier 	for(i = 0; i < nenv; i++)
159*a81c3ea0SDavid du Colombier 		if(cistrcmp(bootenvname[i], name) == 0)
160*a81c3ea0SDavid du Colombier 			return i;
161*a81c3ea0SDavid du Colombier 	return -1;
162*a81c3ea0SDavid du Colombier }
163*a81c3ea0SDavid du Colombier 
164*a81c3ea0SDavid du Colombier static char*
getbootenv(char * name)165*a81c3ea0SDavid du Colombier getbootenv(char *name)
166*a81c3ea0SDavid du Colombier {
167*a81c3ea0SDavid du Colombier 	int i;
168*a81c3ea0SDavid du Colombier 
169*a81c3ea0SDavid du Colombier 	i = findbootenv(name);
170*a81c3ea0SDavid du Colombier 	if(i >= 0)
171*a81c3ea0SDavid du Colombier 		return bootenvval[i];
172*a81c3ea0SDavid du Colombier 	return nil;
173*a81c3ea0SDavid du Colombier }
174*a81c3ea0SDavid du Colombier 
175*a81c3ea0SDavid du Colombier void
confinit(void)176*a81c3ea0SDavid du Colombier confinit(void)
177*a81c3ea0SDavid du Colombier {
178*a81c3ea0SDavid du Colombier 	char *p;
179*a81c3ea0SDavid du Colombier 	int i;
180*a81c3ea0SDavid du Colombier 	ulong kpages, ktop;
181*a81c3ea0SDavid du Colombier 	ulong maxmem, highmemsize;
182*a81c3ea0SDavid du Colombier 
183*a81c3ea0SDavid du Colombier 	/* memory size */
184*a81c3ea0SDavid du Colombier 	memsize = MEMSIZE;
185*a81c3ea0SDavid du Colombier 	if((p = getbootenv("memsize")) != nil)
186*a81c3ea0SDavid du Colombier 		memsize = strtoul(p, 0, 0) * MB;
187*a81c3ea0SDavid du Colombier 	highmemsize = 0;
188*a81c3ea0SDavid du Colombier 	if((p = getbootenv("highmemsize")) != nil)
189*a81c3ea0SDavid du Colombier 		highmemsize = strtoul(p, 0, 0) * MB;
190*a81c3ea0SDavid du Colombier 	if((p = getconf("*maxmem")) != nil){
191*a81c3ea0SDavid du Colombier 		maxmem = strtoul(p, 0, 0);
192*a81c3ea0SDavid du Colombier 		memsize = MIN(memsize, maxmem);
193*a81c3ea0SDavid du Colombier 		maxmem -= memsize;
194*a81c3ea0SDavid du Colombier 		highmemsize = MIN(highmemsize, maxmem);
195*a81c3ea0SDavid du Colombier 		if(memsize < 16*MB)		/* sanity */
196*a81c3ea0SDavid du Colombier 			memsize = 16*MB;
197*a81c3ea0SDavid du Colombier 	}
198*a81c3ea0SDavid du Colombier 
199*a81c3ea0SDavid du Colombier 	/* set up other configuration parameters */
200*a81c3ea0SDavid du Colombier 	conf.nproc = 2000;
201*a81c3ea0SDavid du Colombier 	conf.nswap = 262144;
202*a81c3ea0SDavid du Colombier 	conf.nswppo = 4096;
203*a81c3ea0SDavid du Colombier 	conf.nimage = 200;
204*a81c3ea0SDavid du Colombier 
205*a81c3ea0SDavid du Colombier 	/*
206*a81c3ea0SDavid du Colombier 	 *  divide memory to user pages and kernel.
207*a81c3ea0SDavid du Colombier 	 */
208*a81c3ea0SDavid du Colombier 	conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
209*a81c3ea0SDavid du Colombier 	conf.mem[0].npage = memsize/BY2PG - ktop/BY2PG;
210*a81c3ea0SDavid du Colombier 
211*a81c3ea0SDavid du Colombier 	conf.mem[1].base = HIGHMEM;
212*a81c3ea0SDavid du Colombier 	conf.mem[1].npage = highmemsize/BY2PG;
213*a81c3ea0SDavid du Colombier 
214*a81c3ea0SDavid du Colombier 	conf.npage = 0;
215*a81c3ea0SDavid du Colombier 	for(i=0; i<nelem(conf.mem); i++)
216*a81c3ea0SDavid du Colombier 		conf.npage += conf.mem[i].npage;
217*a81c3ea0SDavid du Colombier 
218*a81c3ea0SDavid du Colombier 	kpages = conf.npage - (conf.npage*80)/100;
219*a81c3ea0SDavid du Colombier 	if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
220*a81c3ea0SDavid du Colombier 		kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
221*a81c3ea0SDavid du Colombier 		kpages += (conf.nproc*KSTACK)/BY2PG;
222*a81c3ea0SDavid du Colombier 	}
223*a81c3ea0SDavid du Colombier 	conf.upages = conf.npage - kpages;
224*a81c3ea0SDavid du Colombier 	conf.ialloc = (kpages/2)*BY2PG;
225*a81c3ea0SDavid du Colombier 
226*a81c3ea0SDavid du Colombier 	kpages *= BY2PG;
227*a81c3ea0SDavid du Colombier 	kpages -= conf.upages*sizeof(Page)
228*a81c3ea0SDavid du Colombier 		+ conf.nproc*sizeof(Proc)
229*a81c3ea0SDavid du Colombier 		+ conf.nimage*sizeof(Image)
230*a81c3ea0SDavid du Colombier 		+ conf.nswap
231*a81c3ea0SDavid du Colombier 		+ conf.nswppo*sizeof(Page);
232*a81c3ea0SDavid du Colombier 	mainmem->maxsize = kpages;
233*a81c3ea0SDavid du Colombier 
234*a81c3ea0SDavid du Colombier 	/*
235*a81c3ea0SDavid du Colombier 	 *  set up CPU's mach structure
236*a81c3ea0SDavid du Colombier 	 *  cpu0's was zeroed in main() and our stack is in Mach, so don't zero it.
237*a81c3ea0SDavid du Colombier 	 */
238*a81c3ea0SDavid du Colombier 	m->machno = 0;
239*a81c3ea0SDavid du Colombier 	m->hz = cpufreq;		/* initial guess at MHz */
240*a81c3ea0SDavid du Colombier 	m->speed = m->hz / Mhz;
241*a81c3ea0SDavid du Colombier 	conf.nmach = 1;
242*a81c3ea0SDavid du Colombier 
243*a81c3ea0SDavid du Colombier 	conf.nuart = 1;
244*a81c3ea0SDavid du Colombier 	conf.copymode = 0;		/* copy on write */
245*a81c3ea0SDavid du Colombier }
246*a81c3ea0SDavid du Colombier 
247*a81c3ea0SDavid du Colombier void
procrestore(Proc * p)248*a81c3ea0SDavid du Colombier procrestore(Proc *p)
249*a81c3ea0SDavid du Colombier {
250*a81c3ea0SDavid du Colombier 	uvlong t;
251*a81c3ea0SDavid du Colombier 
252*a81c3ea0SDavid du Colombier 	if(p->kp)
253*a81c3ea0SDavid du Colombier 		return;
254*a81c3ea0SDavid du Colombier 	cycles(&t);
255*a81c3ea0SDavid du Colombier 	p->pcycles -= t;
256*a81c3ea0SDavid du Colombier }
257*a81c3ea0SDavid du Colombier 
258*a81c3ea0SDavid du Colombier /*
259*a81c3ea0SDavid du Colombier  *  Save the mach dependent part of the process state.
260*a81c3ea0SDavid du Colombier  */
261*a81c3ea0SDavid du Colombier void
procsave(Proc * p)262*a81c3ea0SDavid du Colombier procsave(Proc *p)
263*a81c3ea0SDavid du Colombier {
264*a81c3ea0SDavid du Colombier 	uvlong t;
265*a81c3ea0SDavid du Colombier 
266*a81c3ea0SDavid du Colombier 	cycles(&t);
267*a81c3ea0SDavid du Colombier 	p->pcycles += t;
268*a81c3ea0SDavid du Colombier 	//fpuprocsave(); // XXX
269*a81c3ea0SDavid du Colombier }
270*a81c3ea0SDavid du Colombier 
271*a81c3ea0SDavid du Colombier static void
fmtinit(void)272*a81c3ea0SDavid du Colombier fmtinit(void)
273*a81c3ea0SDavid du Colombier {
274*a81c3ea0SDavid du Colombier 	printinit();
275*a81c3ea0SDavid du Colombier 	quotefmtinstall();
276*a81c3ea0SDavid du Colombier 	/* ipreset installs these when chandevreset runs */
277*a81c3ea0SDavid du Colombier 	fmtinstall('i', eipfmt);
278*a81c3ea0SDavid du Colombier 	fmtinstall('I', eipfmt);
279*a81c3ea0SDavid du Colombier 	fmtinstall('E', eipfmt);
280*a81c3ea0SDavid du Colombier 	fmtinstall('V', eipfmt);
281*a81c3ea0SDavid du Colombier 	fmtinstall('M', eipfmt);
282*a81c3ea0SDavid du Colombier }
283*a81c3ea0SDavid du Colombier 
284*a81c3ea0SDavid du Colombier /*
285*a81c3ea0SDavid du Colombier  *  setup MIPS trap vectors
286*a81c3ea0SDavid du Colombier  */
287*a81c3ea0SDavid du Colombier void
vecinit(void)288*a81c3ea0SDavid du Colombier vecinit(void)
289*a81c3ea0SDavid du Colombier {
290*a81c3ea0SDavid du Colombier 	memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
291*a81c3ea0SDavid du Colombier 	memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
292*a81c3ea0SDavid du Colombier 	memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
293*a81c3ea0SDavid du Colombier 	memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
294*a81c3ea0SDavid du Colombier 	/* 0x200 not used in looongson 2e */
295*a81c3ea0SDavid du Colombier 	icflush((ulong*)UTLBMISS, 4*1024);
296*a81c3ea0SDavid du Colombier 
297*a81c3ea0SDavid du Colombier 	setstatus(getstatus() & ~BEV);
298*a81c3ea0SDavid du Colombier }
299*a81c3ea0SDavid du Colombier 
300*a81c3ea0SDavid du Colombier static void
prcpuid(void)301*a81c3ea0SDavid du Colombier prcpuid(void)
302*a81c3ea0SDavid du Colombier {
303*a81c3ea0SDavid du Colombier 	ulong cpuid, cfg;
304*a81c3ea0SDavid du Colombier 	char *cpu;
305*a81c3ea0SDavid du Colombier 
306*a81c3ea0SDavid du Colombier 	cpuid = prid();
307*a81c3ea0SDavid du Colombier 	cfg = getconfig();
308*a81c3ea0SDavid du Colombier 	if (((cpuid>>16) & MASK(8)) == 0)		/* vendor */
309*a81c3ea0SDavid du Colombier 		cpu = "old mips";
310*a81c3ea0SDavid du Colombier 	else if (((cpuid>>16) & MASK(8)) == 1)
311*a81c3ea0SDavid du Colombier 		switch ((cpuid>>8) & MASK(8)) {		/* processor */
312*a81c3ea0SDavid du Colombier 		case 0x93:
313*a81c3ea0SDavid du Colombier 			cpu = "mips 24k";
314*a81c3ea0SDavid du Colombier 			break;
315*a81c3ea0SDavid du Colombier 		case 0x96:
316*a81c3ea0SDavid du Colombier 			cpu = "mips 24ke";
317*a81c3ea0SDavid du Colombier 			break;
318*a81c3ea0SDavid du Colombier 		default:
319*a81c3ea0SDavid du Colombier 			cpu = "mips";
320*a81c3ea0SDavid du Colombier 			break;
321*a81c3ea0SDavid du Colombier 		}
322*a81c3ea0SDavid du Colombier 	else
323*a81c3ea0SDavid du Colombier 		cpu = "other mips";
324*a81c3ea0SDavid du Colombier 	delay(200);
325*a81c3ea0SDavid du Colombier 	print("cpu%d: %ldMHz %s %se 0x%ulx v%ld.%ld rev %ld has fpu\n",
326*a81c3ea0SDavid du Colombier 		m->machno, m->hz / Mhz, cpu, cfg & (1<<15)? "b": "l",
327*a81c3ea0SDavid du Colombier 		(cpuid>>8) & MASK(8), (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3),
328*a81c3ea0SDavid du Colombier 		cpuid & MASK(2));
329*a81c3ea0SDavid du Colombier 	delay(200);
330*a81c3ea0SDavid du Colombier 
331*a81c3ea0SDavid du Colombier 	print("cpu%d: %d tlb entries, using %dK pages\n", m->machno,
332*a81c3ea0SDavid du Colombier 		64, BY2PG/1024);
333*a81c3ea0SDavid du Colombier 	delay(50);
334*a81c3ea0SDavid du Colombier 	print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
335*a81c3ea0SDavid du Colombier 		32 << ((cfg>>9) & MASK(3)));
336*a81c3ea0SDavid du Colombier 	delay(50);
337*a81c3ea0SDavid du Colombier 	print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
338*a81c3ea0SDavid du Colombier 		32 << ((cfg>>6) & MASK(3)));
339*a81c3ea0SDavid du Colombier 	delay(500);
340*a81c3ea0SDavid du Colombier }
341*a81c3ea0SDavid du Colombier 
342*a81c3ea0SDavid du Colombier static int
ckpagemask(ulong mask,ulong size)343*a81c3ea0SDavid du Colombier ckpagemask(ulong mask, ulong size)
344*a81c3ea0SDavid du Colombier {
345*a81c3ea0SDavid du Colombier 	int s;
346*a81c3ea0SDavid du Colombier 	ulong pm;
347*a81c3ea0SDavid du Colombier 
348*a81c3ea0SDavid du Colombier 	s = splhi();
349*a81c3ea0SDavid du Colombier 	setpagemask(mask);
350*a81c3ea0SDavid du Colombier 	pm = getpagemask();
351*a81c3ea0SDavid du Colombier 	splx(s);
352*a81c3ea0SDavid du Colombier 	if(pm != mask){
353*a81c3ea0SDavid du Colombier 		iprint("page size %ldK not supported on this cpu; "
354*a81c3ea0SDavid du Colombier 			"mask %#lux read back as %#lux\n", size/1024, mask, pm);
355*a81c3ea0SDavid du Colombier 		return -1;
356*a81c3ea0SDavid du Colombier 	}
357*a81c3ea0SDavid du Colombier 	return 0;
358*a81c3ea0SDavid du Colombier }
359*a81c3ea0SDavid du Colombier 
360*a81c3ea0SDavid du Colombier void
init0(void)361*a81c3ea0SDavid du Colombier init0(void)
362*a81c3ea0SDavid du Colombier {
363*a81c3ea0SDavid du Colombier 	char buf[128];
364*a81c3ea0SDavid du Colombier 	int i;
365*a81c3ea0SDavid du Colombier 
366*a81c3ea0SDavid du Colombier 	up->nerrlab = 0;
367*a81c3ea0SDavid du Colombier 
368*a81c3ea0SDavid du Colombier 	spllo();
369*a81c3ea0SDavid du Colombier 
370*a81c3ea0SDavid du Colombier 	/*
371*a81c3ea0SDavid du Colombier 	 * These are o.k. because rootinit is null.
372*a81c3ea0SDavid du Colombier 	 * Then early kproc's will have a root and dot.
373*a81c3ea0SDavid du Colombier 	 */
374*a81c3ea0SDavid du Colombier 	up->slash = namec("#/", Atodir, 0, 0);
375*a81c3ea0SDavid du Colombier 	pathclose(up->slash->path);
376*a81c3ea0SDavid du Colombier 	up->slash->path = newpath("/");
377*a81c3ea0SDavid du Colombier 	up->dot = cclone(up->slash);
378*a81c3ea0SDavid du Colombier 
379*a81c3ea0SDavid du Colombier 	chandevinit();
380*a81c3ea0SDavid du Colombier 
381*a81c3ea0SDavid du Colombier 	if(!waserror()){
382*a81c3ea0SDavid du Colombier 		ksetenv("cputype", "spim", 0);
383*a81c3ea0SDavid du Colombier 		snprint(buf, sizeof buf, "spim %s loongson 2f", conffile);
384*a81c3ea0SDavid du Colombier 		ksetenv("terminal", buf, 0);
385*a81c3ea0SDavid du Colombier 		if(cpuserver)
386*a81c3ea0SDavid du Colombier 			ksetenv("service", "cpu", 0);
387*a81c3ea0SDavid du Colombier 		else
388*a81c3ea0SDavid du Colombier 			ksetenv("service", "terminal", 0);
389*a81c3ea0SDavid du Colombier //		ksetenv("nobootprompt", "local!/boot/bzroot", 0); // for bzroot
390*a81c3ea0SDavid du Colombier 		ksetenv("nvram", "/boot/nvram", 0);
391*a81c3ea0SDavid du Colombier 		/* convert plan9.ini variables to #e and #ec */
392*a81c3ea0SDavid du Colombier 		for(i = 0; i < nconf; i++) {
393*a81c3ea0SDavid du Colombier 			if(*confname[i] == '*')
394*a81c3ea0SDavid du Colombier 				continue;
395*a81c3ea0SDavid du Colombier 			ksetenv(confname[i], confval[i], 0);
396*a81c3ea0SDavid du Colombier 			ksetenv(confname[i], confval[i], 1);
397*a81c3ea0SDavid du Colombier 		}
398*a81c3ea0SDavid du Colombier 		poperror();
399*a81c3ea0SDavid du Colombier 	}
400*a81c3ea0SDavid du Colombier 	kproc("alarm", alarmkproc, 0);
401*a81c3ea0SDavid du Colombier //	i8250console();
402*a81c3ea0SDavid du Colombier 	touser(sp);
403*a81c3ea0SDavid du Colombier }
404*a81c3ea0SDavid du Colombier 
405*a81c3ea0SDavid du Colombier static void
bootargs(uintptr base)406*a81c3ea0SDavid du Colombier bootargs(uintptr base)
407*a81c3ea0SDavid du Colombier {
408*a81c3ea0SDavid du Colombier 	int i;
409*a81c3ea0SDavid du Colombier 	ulong ssize;
410*a81c3ea0SDavid du Colombier 	char **av, *p;
411*a81c3ea0SDavid du Colombier 
412*a81c3ea0SDavid du Colombier 	/*
413*a81c3ea0SDavid du Colombier 	 * Push the boot args onto the stack.
414*a81c3ea0SDavid du Colombier 	 * The initial value of the user stack must be such
415*a81c3ea0SDavid du Colombier 	 * that the total used is larger than the maximum size
416*a81c3ea0SDavid du Colombier 	 * of the argument list checked in syscall.
417*a81c3ea0SDavid du Colombier 	 */
418*a81c3ea0SDavid du Colombier 	i = oargblen+1;
419*a81c3ea0SDavid du Colombier 	p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));
420*a81c3ea0SDavid du Colombier 	memmove(p, oargb, i);
421*a81c3ea0SDavid du Colombier 
422*a81c3ea0SDavid du Colombier 	/*
423*a81c3ea0SDavid du Colombier 	 * Now push the argv pointers.
424*a81c3ea0SDavid du Colombier 	 * The code jumped to by touser in l.s expects arguments
425*a81c3ea0SDavid du Colombier 	 *	main(char* argv0, ...)
426*a81c3ea0SDavid du Colombier 	 * and calls
427*a81c3ea0SDavid du Colombier 	 * 	startboot("/boot/boot", &argv0)
428*a81c3ea0SDavid du Colombier 	 * not the usual (int argc, char* argv[])
429*a81c3ea0SDavid du Colombier 	 */
430*a81c3ea0SDavid du Colombier 	av = (char**)(p - (oargc+1)*sizeof(char*));
431*a81c3ea0SDavid du Colombier 	ssize = base + BY2PG - PTR2UINT(av);
432*a81c3ea0SDavid du Colombier 	for(i = 0; i < oargc; i++)
433*a81c3ea0SDavid du Colombier 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
434*a81c3ea0SDavid du Colombier 	*av = nil;
435*a81c3ea0SDavid du Colombier 	sp = USTKTOP - ssize;
436*a81c3ea0SDavid du Colombier }
437*a81c3ea0SDavid du Colombier 
438*a81c3ea0SDavid du Colombier void
userinit(void)439*a81c3ea0SDavid du Colombier userinit(void)
440*a81c3ea0SDavid du Colombier {
441*a81c3ea0SDavid du Colombier 	Proc *p;
442*a81c3ea0SDavid du Colombier 	KMap *k;
443*a81c3ea0SDavid du Colombier 	Page *pg;
444*a81c3ea0SDavid du Colombier 	Segment *s;
445*a81c3ea0SDavid du Colombier 
446*a81c3ea0SDavid du Colombier 	p = newproc();
447*a81c3ea0SDavid du Colombier 	p->pgrp = newpgrp();
448*a81c3ea0SDavid du Colombier 	p->egrp = smalloc(sizeof(Egrp));
449*a81c3ea0SDavid du Colombier 	p->egrp->ref = 1;
450*a81c3ea0SDavid du Colombier 	p->fgrp = dupfgrp(nil);
451*a81c3ea0SDavid du Colombier 	p->rgrp = newrgrp();
452*a81c3ea0SDavid du Colombier 	p->procmode = 0640;
453*a81c3ea0SDavid du Colombier 
454*a81c3ea0SDavid du Colombier 	kstrdup(&eve, "");
455*a81c3ea0SDavid du Colombier 	kstrdup(&p->text, "*init*");
456*a81c3ea0SDavid du Colombier 	kstrdup(&p->user, eve);
457*a81c3ea0SDavid du Colombier 
458*a81c3ea0SDavid du Colombier 	p->fpstate = FPinit;
459*a81c3ea0SDavid du Colombier 	p->fpsave.fpstatus = initfp.fpstatus;
460*a81c3ea0SDavid du Colombier 
461*a81c3ea0SDavid du Colombier 	/*
462*a81c3ea0SDavid du Colombier 	 * Kernel Stack
463*a81c3ea0SDavid du Colombier 	 */
464*a81c3ea0SDavid du Colombier 	p->sched.pc = (ulong)init0;
465*a81c3ea0SDavid du Colombier 	p->sched.sp = (ulong)p->kstack+KSTACK-Stkheadroom;
466*a81c3ea0SDavid du Colombier 	p->sched.sp = STACKALIGN(p->sched.sp);
467*a81c3ea0SDavid du Colombier 
468*a81c3ea0SDavid du Colombier 	/*
469*a81c3ea0SDavid du Colombier 	 * User Stack
470*a81c3ea0SDavid du Colombier 	 *
471*a81c3ea0SDavid du Colombier 	 * Technically, newpage can't be called here because it
472*a81c3ea0SDavid du Colombier 	 * should only be called when in a user context as it may
473*a81c3ea0SDavid du Colombier 	 * try to sleep if there are no pages available, but that
474*a81c3ea0SDavid du Colombier 	 * shouldn't be the case here.
475*a81c3ea0SDavid du Colombier 	 */
476*a81c3ea0SDavid du Colombier 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
477*a81c3ea0SDavid du Colombier 	p->seg[SSEG] = s;
478*a81c3ea0SDavid du Colombier 	pg = newpage(1, 0, USTKTOP-BY2PG);
479*a81c3ea0SDavid du Colombier 	memset(pg->cachectl, PG_DATFLUSH, sizeof(pg->cachectl));
480*a81c3ea0SDavid du Colombier 	segpage(s, pg);
481*a81c3ea0SDavid du Colombier 	k = kmap(pg);
482*a81c3ea0SDavid du Colombier 	bootargs(VA(k));
483*a81c3ea0SDavid du Colombier 	kunmap(k);
484*a81c3ea0SDavid du Colombier 
485*a81c3ea0SDavid du Colombier 	/*
486*a81c3ea0SDavid du Colombier 	 * Text
487*a81c3ea0SDavid du Colombier 	 */
488*a81c3ea0SDavid du Colombier 	s = newseg(SG_TEXT, UTZERO, 1);
489*a81c3ea0SDavid du Colombier 	s->flushme++;
490*a81c3ea0SDavid du Colombier 	p->seg[TSEG] = s;
491*a81c3ea0SDavid du Colombier 	pg = newpage(1, 0, UTZERO);
492*a81c3ea0SDavid du Colombier 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
493*a81c3ea0SDavid du Colombier 	segpage(s, pg);
494*a81c3ea0SDavid du Colombier 	k = kmap(s->map[0]->pages[0]);
495*a81c3ea0SDavid du Colombier 	memset((void*)VA(k), 0, BY2PG);
496*a81c3ea0SDavid du Colombier 	memmove((ulong*)VA(k), initcode, sizeof initcode);
497*a81c3ea0SDavid du Colombier 	kunmap(k);
498*a81c3ea0SDavid du Colombier 
499*a81c3ea0SDavid du Colombier 	ready(p);
500*a81c3ea0SDavid du Colombier }
501*a81c3ea0SDavid du Colombier 
502*a81c3ea0SDavid du Colombier /* called from rebootcmd() */
503*a81c3ea0SDavid du Colombier int
parsemipsboothdr(Chan * c,ulong magic,Execvals * evp)504*a81c3ea0SDavid du Colombier parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
505*a81c3ea0SDavid du Colombier {
506*a81c3ea0SDavid du Colombier 	long extra;
507*a81c3ea0SDavid du Colombier 	Mipsexec me;
508*a81c3ea0SDavid du Colombier 
509*a81c3ea0SDavid du Colombier 	/*
510*a81c3ea0SDavid du Colombier 	 * BOOT_MAGIC is sometimes defined like this:
511*a81c3ea0SDavid du Colombier 	 * #define BOOT_MAGIC	(0x160<<16) || magic == ((0x160<<16)|3)
512*a81c3ea0SDavid du Colombier 	 * so we can only use it in a fairly stylized manner.
513*a81c3ea0SDavid du Colombier 	 */
514*a81c3ea0SDavid du Colombier 	if(magic == BOOT_MAGIC) {
515*a81c3ea0SDavid du Colombier 		c->offset = 0;			/* back up */
516*a81c3ea0SDavid du Colombier 		readn(c, &me, sizeof me);
517*a81c3ea0SDavid du Colombier 		/* if binary is -H1, read an extra long */
518*a81c3ea0SDavid du Colombier 		if (l2be(me.amagic) == 0407 && me.nscns == 0)
519*a81c3ea0SDavid du Colombier 			readn(c, &extra, sizeof extra);
520*a81c3ea0SDavid du Colombier 		evp->entry = l2be(me.mentry);
521*a81c3ea0SDavid du Colombier 		evp->textsize = l2be(me.tsize);
522*a81c3ea0SDavid du Colombier 		evp->datasize = l2be(me.dsize);
523*a81c3ea0SDavid du Colombier 		return 0;
524*a81c3ea0SDavid du Colombier 	} else
525*a81c3ea0SDavid du Colombier 		return -1;
526*a81c3ea0SDavid du Colombier }
527*a81c3ea0SDavid du Colombier 
528*a81c3ea0SDavid du Colombier void
main(void)529*a81c3ea0SDavid du Colombier main(void)
530*a81c3ea0SDavid du Colombier {
531*a81c3ea0SDavid du Colombier 	extern char edata[], end[];
532*a81c3ea0SDavid du Colombier 
533*a81c3ea0SDavid du Colombier 	m = (Mach*)MACHADDR;
534*a81c3ea0SDavid du Colombier 	memset(m, 0, sizeof(Mach));		/* clear Mach */
535*a81c3ea0SDavid du Colombier 	m->machno = 0;
536*a81c3ea0SDavid du Colombier 	machaddr[m->machno] = m;
537*a81c3ea0SDavid du Colombier 	up = nil;
538*a81c3ea0SDavid du Colombier 	memset(edata, 0, end-edata);	/* clear bss */
539*a81c3ea0SDavid du Colombier 
540*a81c3ea0SDavid du Colombier 	optionsinit("/boot/boot boot");
541*a81c3ea0SDavid du Colombier 	plan9iniinit();
542*a81c3ea0SDavid du Colombier 	confinit();
543*a81c3ea0SDavid du Colombier 	savefpregs(&initfp);
544*a81c3ea0SDavid du Colombier 
545*a81c3ea0SDavid du Colombier 	machinit();
546*a81c3ea0SDavid du Colombier 	active.exiting = 0;
547*a81c3ea0SDavid du Colombier 	active.machs = 1;
548*a81c3ea0SDavid du Colombier 
549*a81c3ea0SDavid du Colombier 	kmapinit();
550*a81c3ea0SDavid du Colombier 	xinit();
551*a81c3ea0SDavid du Colombier 	screeninit();
552*a81c3ea0SDavid du Colombier 
553*a81c3ea0SDavid du Colombier 	ckpagemask(PGSZ, BY2PG);
554*a81c3ea0SDavid du Colombier 	tlbinit();
555*a81c3ea0SDavid du Colombier 	machwire();
556*a81c3ea0SDavid du Colombier 
557*a81c3ea0SDavid du Colombier 	timersinit();
558*a81c3ea0SDavid du Colombier 	fmtinit();
559*a81c3ea0SDavid du Colombier 	vecinit();
560*a81c3ea0SDavid du Colombier 
561*a81c3ea0SDavid du Colombier 	normalprint = 1;
562*a81c3ea0SDavid du Colombier 	print("\nPlan 9\n");
563*a81c3ea0SDavid du Colombier 	print("\0\0\0\0\0\0\0"); // XXX 0c bug fixed -- leave this for sanity
564*a81c3ea0SDavid du Colombier 	prcpuid();
565*a81c3ea0SDavid du Colombier 	if(PTECACHABILITY == PTENONCOHERWT)
566*a81c3ea0SDavid du Colombier 		print("caches configured as write-through\n");
567*a81c3ea0SDavid du Colombier //	xsummary();
568*a81c3ea0SDavid du Colombier 
569*a81c3ea0SDavid du Colombier 	i8259init();
570*a81c3ea0SDavid du Colombier 	kbdinit();
571*a81c3ea0SDavid du Colombier 	if(conf.monitor)
572*a81c3ea0SDavid du Colombier 		swcursorinit();
573*a81c3ea0SDavid du Colombier 
574*a81c3ea0SDavid du Colombier 	pageinit();
575*a81c3ea0SDavid du Colombier 	procinit0();
576*a81c3ea0SDavid du Colombier 	initseg();
577*a81c3ea0SDavid du Colombier 	links();
578*a81c3ea0SDavid du Colombier 	chandevreset();
579*a81c3ea0SDavid du Colombier 
580*a81c3ea0SDavid du Colombier 	swapinit();
581*a81c3ea0SDavid du Colombier 	userinit();
582*a81c3ea0SDavid du Colombier 	parseboothdr = parsemipsboothdr;
583*a81c3ea0SDavid du Colombier 	schedinit();
584*a81c3ea0SDavid du Colombier 	panic("schedinit returned");
585*a81c3ea0SDavid du Colombier }
586*a81c3ea0SDavid du Colombier 
587*a81c3ea0SDavid du Colombier static void
writeconf(void)588*a81c3ea0SDavid du Colombier writeconf(void)
589*a81c3ea0SDavid du Colombier {
590*a81c3ea0SDavid du Colombier 	char *p, *q;
591*a81c3ea0SDavid du Colombier 	int n;
592*a81c3ea0SDavid du Colombier 
593*a81c3ea0SDavid du Colombier 	p = getconfenv();
594*a81c3ea0SDavid du Colombier 
595*a81c3ea0SDavid du Colombier 	if(waserror()) {
596*a81c3ea0SDavid du Colombier 		free(p);
597*a81c3ea0SDavid du Colombier 		nexterror();
598*a81c3ea0SDavid du Colombier 	}
599*a81c3ea0SDavid du Colombier 
600*a81c3ea0SDavid du Colombier 	/* convert to name=value\0 format */
601*a81c3ea0SDavid du Colombier 	_argc = 1;		/* skip _argv[0] */
602*a81c3ea0SDavid du Colombier 	_argv = (void*)CONFARGV;
603*a81c3ea0SDavid du Colombier 	_argv[0] = BOOTARGS;
604*a81c3ea0SDavid du Colombier 	for(q=p; *q; q++) {
605*a81c3ea0SDavid du Colombier 		_argv[_argc] = (char*)((ulong)BOOTARGS + (q - p));
606*a81c3ea0SDavid du Colombier 		_argc++;
607*a81c3ea0SDavid du Colombier 		q += strlen(q);
608*a81c3ea0SDavid du Colombier 		*q = '=';
609*a81c3ea0SDavid du Colombier 		q += strlen(q);
610*a81c3ea0SDavid du Colombier 	}
611*a81c3ea0SDavid du Colombier 	n = q - p + 1;
612*a81c3ea0SDavid du Colombier 	_env = &_argv[_argc];
613*a81c3ea0SDavid du Colombier 
614*a81c3ea0SDavid du Colombier 	if(n >= BOOTARGSLEN || (ulong)_env >= CONFARGV + CONFARGVLEN)
615*a81c3ea0SDavid du Colombier 		error("kernel configuration too large");
616*a81c3ea0SDavid du Colombier 	memmove(BOOTARGS, p, n);
617*a81c3ea0SDavid du Colombier 	memset(BOOTARGS + n, '\0', BOOTARGSLEN - n);
618*a81c3ea0SDavid du Colombier 	memset(_env, 0, CONFARGV + CONFARGVLEN - (ulong)_env);
619*a81c3ea0SDavid du Colombier 
620*a81c3ea0SDavid du Colombier 	poperror();
621*a81c3ea0SDavid du Colombier 	free(p);
622*a81c3ea0SDavid du Colombier }
623*a81c3ea0SDavid du Colombier 
624*a81c3ea0SDavid du Colombier static void
shutdown(int ispanic)625*a81c3ea0SDavid du Colombier shutdown(int ispanic)
626*a81c3ea0SDavid du Colombier {
627*a81c3ea0SDavid du Colombier 	int ms, once;
628*a81c3ea0SDavid du Colombier 
629*a81c3ea0SDavid du Colombier 	ilock(&active);
630*a81c3ea0SDavid du Colombier 	if(ispanic)
631*a81c3ea0SDavid du Colombier 		active.ispanic = ispanic;
632*a81c3ea0SDavid du Colombier 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
633*a81c3ea0SDavid du Colombier 		active.ispanic = 0;
634*a81c3ea0SDavid du Colombier 	once = active.machs & (1<<m->machno);
635*a81c3ea0SDavid du Colombier 	/*
636*a81c3ea0SDavid du Colombier 	 * setting exiting will make hzclock() on each processor call exit(0),
637*a81c3ea0SDavid du Colombier 	 * which calls shutdown(0) and idles non-bootstrap cpus and returns
638*a81c3ea0SDavid du Colombier 	 * on bootstrap processors (to permit a reboot).  clearing our bit
639*a81c3ea0SDavid du Colombier 	 * in machs avoids calling exit(0) from hzclock() on this processor.
640*a81c3ea0SDavid du Colombier 	 */
641*a81c3ea0SDavid du Colombier 	active.machs &= ~(1<<m->machno);
642*a81c3ea0SDavid du Colombier 	active.exiting = 1;
643*a81c3ea0SDavid du Colombier 	iunlock(&active);
644*a81c3ea0SDavid du Colombier 
645*a81c3ea0SDavid du Colombier 	if(once) {
646*a81c3ea0SDavid du Colombier 		delay(m->machno*1000);		/* stagger them */
647*a81c3ea0SDavid du Colombier 		iprint("cpu%d: exiting\n", m->machno);
648*a81c3ea0SDavid du Colombier 	}
649*a81c3ea0SDavid du Colombier 	spllo();
650*a81c3ea0SDavid du Colombier 	for(ms = MAXMACH * 1000; ms > 0; ms -= TK2MS(2)){
651*a81c3ea0SDavid du Colombier 		delay(TK2MS(2));
652*a81c3ea0SDavid du Colombier 		if(active.machs == 0 && consactive() == 0)
653*a81c3ea0SDavid du Colombier 			break;
654*a81c3ea0SDavid du Colombier 	}
655*a81c3ea0SDavid du Colombier 	delay(100);
656*a81c3ea0SDavid du Colombier }
657*a81c3ea0SDavid du Colombier 
658*a81c3ea0SDavid du Colombier void
exit(int ispanic)659*a81c3ea0SDavid du Colombier exit(int ispanic)
660*a81c3ea0SDavid du Colombier {
661*a81c3ea0SDavid du Colombier 	int timer;
662*a81c3ea0SDavid du Colombier 
663*a81c3ea0SDavid du Colombier 	delay(1000);
664*a81c3ea0SDavid du Colombier 	shutdown(ispanic);
665*a81c3ea0SDavid du Colombier 	timer = 0;
666*a81c3ea0SDavid du Colombier 	while(active.machs || consactive()) {
667*a81c3ea0SDavid du Colombier 		if(timer++ > 400)
668*a81c3ea0SDavid du Colombier 			break;
669*a81c3ea0SDavid du Colombier 		delay(10);
670*a81c3ea0SDavid du Colombier 	}
671*a81c3ea0SDavid du Colombier 	delay(1000);
672*a81c3ea0SDavid du Colombier 	splhi();
673*a81c3ea0SDavid du Colombier 
674*a81c3ea0SDavid du Colombier 	setstatus(BEV);
675*a81c3ea0SDavid du Colombier 	coherence();
676*a81c3ea0SDavid du Colombier 
677*a81c3ea0SDavid du Colombier 	iprint("exit: awaiting reset\n");
678*a81c3ea0SDavid du Colombier 	delay(1000);			/* await a reset */
679*a81c3ea0SDavid du Colombier 
680*a81c3ea0SDavid du Colombier 	if(!active.ispanic) {
681*a81c3ea0SDavid du Colombier 		iprint("exit: jumping to rom\n");
682*a81c3ea0SDavid du Colombier //		*Reset |= Rstcpucold;		/* cpu cold reset */
683*a81c3ea0SDavid du Colombier 		outb(0x381, 0xf4);
684*a81c3ea0SDavid du Colombier 		outb(0x382, 0xec);
685*a81c3ea0SDavid du Colombier 		outb(0x383, 1);
686*a81c3ea0SDavid du Colombier 	}
687*a81c3ea0SDavid du Colombier 
688*a81c3ea0SDavid du Colombier 	iprint("exit: looping\n");
689*a81c3ea0SDavid du Colombier 	for(;;);
690*a81c3ea0SDavid du Colombier }
691*a81c3ea0SDavid du Colombier 
692*a81c3ea0SDavid du Colombier /*
693*a81c3ea0SDavid du Colombier  * the new kernel is already loaded at address `code'
694*a81c3ea0SDavid du Colombier  * of size `size' and entry point `entry'.
695*a81c3ea0SDavid du Colombier  */
696*a81c3ea0SDavid du Colombier void
reboot(void * entry,void * code,ulong size)697*a81c3ea0SDavid du Colombier reboot(void *entry, void *code, ulong size)
698*a81c3ea0SDavid du Colombier {
699*a81c3ea0SDavid du Colombier 	void (*f)(ulong, ulong, ulong, ulong);
700*a81c3ea0SDavid du Colombier 
701*a81c3ea0SDavid du Colombier 	writeconf();
702*a81c3ea0SDavid du Colombier 
703*a81c3ea0SDavid du Colombier 	/*
704*a81c3ea0SDavid du Colombier 	 * the boot processor is cpu0.  execute this function on it
705*a81c3ea0SDavid du Colombier 	 * so that the new kernel has the same cpu0.
706*a81c3ea0SDavid du Colombier 	 */
707*a81c3ea0SDavid du Colombier 	if(m->machno != 0) {
708*a81c3ea0SDavid du Colombier 		procwired(up, 0);
709*a81c3ea0SDavid du Colombier 		sched();
710*a81c3ea0SDavid du Colombier 	}
711*a81c3ea0SDavid du Colombier 	if(m->machno != 0)
712*a81c3ea0SDavid du Colombier 		print("on cpu%d (not 0)!\n", m->machno);
713*a81c3ea0SDavid du Colombier 
714*a81c3ea0SDavid du Colombier 	if(code == nil || entry == nil)
715*a81c3ea0SDavid du Colombier 		exit(1);
716*a81c3ea0SDavid du Colombier 
717*a81c3ea0SDavid du Colombier 	shutdown(0);
718*a81c3ea0SDavid du Colombier 
719*a81c3ea0SDavid du Colombier 	/*
720*a81c3ea0SDavid du Colombier 	 * should be the only processor running now
721*a81c3ea0SDavid du Colombier 	 */
722*a81c3ea0SDavid du Colombier 	iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
723*a81c3ea0SDavid du Colombier 	iprint("code[0] = %#lux\n", *(ulong *)code);
724*a81c3ea0SDavid du Colombier 
725*a81c3ea0SDavid du Colombier 	/* turn off buffered serial console */
726*a81c3ea0SDavid du Colombier 	serialoq = nil;
727*a81c3ea0SDavid du Colombier 	kprintoq = nil;
728*a81c3ea0SDavid du Colombier 	screenputs = nil;
729*a81c3ea0SDavid du Colombier 
730*a81c3ea0SDavid du Colombier 	/* shutdown devices */
731*a81c3ea0SDavid du Colombier 	chandevshutdown();
732*a81c3ea0SDavid du Colombier 
733*a81c3ea0SDavid du Colombier 	splhi();
734*a81c3ea0SDavid du Colombier 	intrshutdown();
735*a81c3ea0SDavid du Colombier 
736*a81c3ea0SDavid du Colombier 	/* setup reboot trampoline function */
737*a81c3ea0SDavid du Colombier 	f = (void*)REBOOTADDR;
738*a81c3ea0SDavid du Colombier 	memmove(f, rebootcode, sizeof(rebootcode));
739*a81c3ea0SDavid du Colombier 	icflush(f, sizeof(rebootcode));
740*a81c3ea0SDavid du Colombier 
741*a81c3ea0SDavid du Colombier 	setstatus(BEV);		/* also, kernel mode, no interrupts */
742*a81c3ea0SDavid du Colombier 	coherence();
743*a81c3ea0SDavid du Colombier 
744*a81c3ea0SDavid du Colombier 	/* off we go - never to return */
745*a81c3ea0SDavid du Colombier 	(*f)((ulong)entry, (ulong)code, size, _argc);
746*a81c3ea0SDavid du Colombier 
747*a81c3ea0SDavid du Colombier 	panic("loaded kernel returned!");
748*a81c3ea0SDavid du Colombier }
749*a81c3ea0SDavid du Colombier 
750*a81c3ea0SDavid du Colombier /*
751*a81c3ea0SDavid du Colombier  * stub for ../port/devpnp.c
752*a81c3ea0SDavid du Colombier  */
753*a81c3ea0SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)754*a81c3ea0SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
755*a81c3ea0SDavid du Colombier {
756*a81c3ea0SDavid du Colombier 	USED(class, ctlrno, isa);
757*a81c3ea0SDavid du Colombier 	return 0;
758*a81c3ea0SDavid du Colombier }
759