xref: /plan9-contrib/sys/src/9/bcm/main.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
15d9de2d3SDavid du Colombier #include "u.h"
25d9de2d3SDavid du Colombier #include "tos.h"
35d9de2d3SDavid du Colombier #include "../port/lib.h"
45d9de2d3SDavid du Colombier #include "mem.h"
55d9de2d3SDavid du Colombier #include "dat.h"
6*5c47fe09SDavid du Colombier #include "io.h"
75d9de2d3SDavid du Colombier #include "fns.h"
85d9de2d3SDavid du Colombier 
95d9de2d3SDavid du Colombier #include "init.h"
105d9de2d3SDavid du Colombier #include <pool.h>
115d9de2d3SDavid du Colombier 
125d9de2d3SDavid du Colombier #include "reboot.h"
135d9de2d3SDavid du Colombier 
1423a96966SDavid du Colombier enum {
1523a96966SDavid du Colombier 	/* space for syscall args, return PC, top-of-stack struct */
1623a96966SDavid du Colombier 	Ustkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
1723a96966SDavid du Colombier };
1823a96966SDavid du Colombier 
195d9de2d3SDavid du Colombier /* Firmware compatibility */
205d9de2d3SDavid du Colombier #define	Minfirmrev	326770
213ec63e64SDavid du Colombier #define	Minfirmdate	"19 Aug 2013"
225d9de2d3SDavid du Colombier 
235d9de2d3SDavid du Colombier /*
245d9de2d3SDavid du Colombier  * Where configuration info is left for the loaded programme.
255d9de2d3SDavid du Colombier  */
265d9de2d3SDavid du Colombier #define BOOTARGS	((char*)CONFADDR)
275d9de2d3SDavid du Colombier #define	BOOTARGSLEN	(MACHADDR-CONFADDR)
285d9de2d3SDavid du Colombier #define	MAXCONF		64
295d9de2d3SDavid du Colombier #define MAXCONFLINE	160
305d9de2d3SDavid du Colombier 
315d9de2d3SDavid du Colombier uintptr kseg0 = KZERO;
325d9de2d3SDavid du Colombier Mach*	machaddr[MAXMACH];
335d9de2d3SDavid du Colombier Conf	conf;
345d9de2d3SDavid du Colombier ulong	memsize = 128*1024*1024;
355d9de2d3SDavid du Colombier 
365d9de2d3SDavid du Colombier /*
375d9de2d3SDavid du Colombier  * Option arguments from the command line.
385d9de2d3SDavid du Colombier  * oargv[0] is the boot file.
395d9de2d3SDavid du Colombier  */
405d9de2d3SDavid du Colombier static int oargc;
415d9de2d3SDavid du Colombier static char* oargv[20];
425d9de2d3SDavid du Colombier static char oargb[128];
435d9de2d3SDavid du Colombier static int oargblen;
445d9de2d3SDavid du Colombier 
455d9de2d3SDavid du Colombier static uintptr sp;		/* XXX - must go - user stack of init proc */
465d9de2d3SDavid du Colombier 
475d9de2d3SDavid du Colombier /* store plan9.ini contents here at least until we stash them in #ec */
485d9de2d3SDavid du Colombier static char confname[MAXCONF][KNAMELEN];
495d9de2d3SDavid du Colombier static char confval[MAXCONF][MAXCONFLINE];
505d9de2d3SDavid du Colombier static int nconf;
515d9de2d3SDavid du Colombier 
525d9de2d3SDavid du Colombier typedef struct Atag Atag;
535d9de2d3SDavid du Colombier struct Atag {
545d9de2d3SDavid du Colombier 	u32int	size;	/* size of atag in words, including this header */
555d9de2d3SDavid du Colombier 	u32int	tag;	/* atag type */
565d9de2d3SDavid du Colombier 	union {
575d9de2d3SDavid du Colombier 		u32int	data[1];	/* actually [size-2] */
585d9de2d3SDavid du Colombier 		/* AtagMem */
595d9de2d3SDavid du Colombier 		struct {
605d9de2d3SDavid du Colombier 			u32int	size;
615d9de2d3SDavid du Colombier 			u32int	base;
625d9de2d3SDavid du Colombier 		} mem;
635d9de2d3SDavid du Colombier 		/* AtagCmdLine */
645d9de2d3SDavid du Colombier 		char	cmdline[1];	/* actually [4*(size-2)] */
655d9de2d3SDavid du Colombier 	};
665d9de2d3SDavid du Colombier };
675d9de2d3SDavid du Colombier 
685d9de2d3SDavid du Colombier enum {
695d9de2d3SDavid du Colombier 	AtagNone	= 0x00000000,
705d9de2d3SDavid du Colombier 	AtagCore	= 0x54410001,
715d9de2d3SDavid du Colombier 	AtagMem		= 0x54410002,
725d9de2d3SDavid du Colombier 	AtagCmdline	= 0x54410009,
735d9de2d3SDavid du Colombier };
745d9de2d3SDavid du Colombier 
755d9de2d3SDavid du Colombier static int
findconf(char * name)765d9de2d3SDavid du Colombier findconf(char *name)
775d9de2d3SDavid du Colombier {
785d9de2d3SDavid du Colombier 	int i;
795d9de2d3SDavid du Colombier 
805d9de2d3SDavid du Colombier 	for(i = 0; i < nconf; i++)
815d9de2d3SDavid du Colombier 		if(cistrcmp(confname[i], name) == 0)
825d9de2d3SDavid du Colombier 			return i;
835d9de2d3SDavid du Colombier 	return -1;
845d9de2d3SDavid du Colombier }
855d9de2d3SDavid du Colombier 
865d9de2d3SDavid du Colombier char*
getconf(char * name)875d9de2d3SDavid du Colombier getconf(char *name)
885d9de2d3SDavid du Colombier {
895d9de2d3SDavid du Colombier 	int i;
905d9de2d3SDavid du Colombier 
915d9de2d3SDavid du Colombier 	i = findconf(name);
925d9de2d3SDavid du Colombier 	if(i >= 0)
935d9de2d3SDavid du Colombier 		return confval[i];
945d9de2d3SDavid du Colombier 	return nil;
955d9de2d3SDavid du Colombier }
965d9de2d3SDavid du Colombier 
975d9de2d3SDavid du Colombier void
addconf(char * name,char * val)985d9de2d3SDavid du Colombier addconf(char *name, char *val)
995d9de2d3SDavid du Colombier {
1005d9de2d3SDavid du Colombier 	int i;
1015d9de2d3SDavid du Colombier 
1025d9de2d3SDavid du Colombier 	i = findconf(name);
1035d9de2d3SDavid du Colombier 	if(i < 0){
1045d9de2d3SDavid du Colombier 		if(val == nil || nconf >= MAXCONF)
1055d9de2d3SDavid du Colombier 			return;
1065d9de2d3SDavid du Colombier 		i = nconf++;
1075d9de2d3SDavid du Colombier 		strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
1085d9de2d3SDavid du Colombier 	}
1095d9de2d3SDavid du Colombier 	strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
1105d9de2d3SDavid du Colombier }
1115d9de2d3SDavid du Colombier 
1125d9de2d3SDavid du Colombier static void
writeconf(void)1135d9de2d3SDavid du Colombier writeconf(void)
1145d9de2d3SDavid du Colombier {
1155d9de2d3SDavid du Colombier 	char *p, *q;
1165d9de2d3SDavid du Colombier 	int n;
1175d9de2d3SDavid du Colombier 
1185d9de2d3SDavid du Colombier 	p = getconfenv();
1195d9de2d3SDavid du Colombier 
1205d9de2d3SDavid du Colombier 	if(waserror()) {
1215d9de2d3SDavid du Colombier 		free(p);
1225d9de2d3SDavid du Colombier 		nexterror();
1235d9de2d3SDavid du Colombier 	}
1245d9de2d3SDavid du Colombier 
1255d9de2d3SDavid du Colombier 	/* convert to name=value\n format */
1265d9de2d3SDavid du Colombier 	for(q=p; *q; q++) {
1275d9de2d3SDavid du Colombier 		q += strlen(q);
1285d9de2d3SDavid du Colombier 		*q = '=';
1295d9de2d3SDavid du Colombier 		q += strlen(q);
1305d9de2d3SDavid du Colombier 		*q = '\n';
1315d9de2d3SDavid du Colombier 	}
1325d9de2d3SDavid du Colombier 	n = q - p + 1;
1335d9de2d3SDavid du Colombier 	if(n >= BOOTARGSLEN)
1345d9de2d3SDavid du Colombier 		error("kernel configuration too large");
1355d9de2d3SDavid du Colombier 	memmove(BOOTARGS, p, n);
1365d9de2d3SDavid du Colombier 	memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
1375d9de2d3SDavid du Colombier 	poperror();
1385d9de2d3SDavid du Colombier 	free(p);
1395d9de2d3SDavid du Colombier }
1405d9de2d3SDavid du Colombier 
1415d9de2d3SDavid du Colombier static void
plan9iniinit(char * s,int cmdline)1425d9de2d3SDavid du Colombier plan9iniinit(char *s, int cmdline)
1435d9de2d3SDavid du Colombier {
1445d9de2d3SDavid du Colombier 	char *toks[MAXCONF];
1455d9de2d3SDavid du Colombier 	int i, c, n;
1465d9de2d3SDavid du Colombier 	char *v;
1475d9de2d3SDavid du Colombier 
1485d9de2d3SDavid du Colombier 	if((c = *s) < ' ' || c >= 0x80)
1495d9de2d3SDavid du Colombier 		return;
1505d9de2d3SDavid du Colombier 	if(cmdline)
1515d9de2d3SDavid du Colombier 		n = tokenize(s, toks, MAXCONF);
1525d9de2d3SDavid du Colombier 	else
1535d9de2d3SDavid du Colombier 		n = getfields(s, toks, MAXCONF, 1, "\n");
1545d9de2d3SDavid du Colombier 	for(i = 0; i < n; i++){
1555d9de2d3SDavid du Colombier 		if(toks[i][0] == '#')
1565d9de2d3SDavid du Colombier 			continue;
1575d9de2d3SDavid du Colombier 		v = strchr(toks[i], '=');
1585d9de2d3SDavid du Colombier 		if(v == nil)
1595d9de2d3SDavid du Colombier 			continue;
1605d9de2d3SDavid du Colombier 		*v++ = '\0';
1615d9de2d3SDavid du Colombier 		addconf(toks[i], v);
1625d9de2d3SDavid du Colombier 	}
1635d9de2d3SDavid du Colombier }
1645d9de2d3SDavid du Colombier 
1655d9de2d3SDavid du Colombier static void
ataginit(Atag * a)1665d9de2d3SDavid du Colombier ataginit(Atag *a)
1675d9de2d3SDavid du Colombier {
1685d9de2d3SDavid du Colombier 	int n;
1695d9de2d3SDavid du Colombier 
1705d9de2d3SDavid du Colombier 	if(a->tag != AtagCore){
1715d9de2d3SDavid du Colombier 		plan9iniinit((char*)a, 0);
1725d9de2d3SDavid du Colombier 		return;
1735d9de2d3SDavid du Colombier 	}
1745d9de2d3SDavid du Colombier 	while(a->tag != AtagNone){
1755d9de2d3SDavid du Colombier 		switch(a->tag){
1765d9de2d3SDavid du Colombier 		case AtagMem:
1775d9de2d3SDavid du Colombier 			/* use only first bank */
1785d9de2d3SDavid du Colombier 			if(conf.mem[0].limit == 0 && a->mem.size != 0){
1795d9de2d3SDavid du Colombier 				memsize = a->mem.size;
1805d9de2d3SDavid du Colombier 				conf.mem[0].base = a->mem.base;
1815d9de2d3SDavid du Colombier 				conf.mem[0].limit = a->mem.base + memsize;
1825d9de2d3SDavid du Colombier 			}
1835d9de2d3SDavid du Colombier 			break;
1845d9de2d3SDavid du Colombier 		case AtagCmdline:
1855d9de2d3SDavid du Colombier 			n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]);
1865d9de2d3SDavid du Colombier 			if(a->cmdline + n < BOOTARGS + BOOTARGSLEN)
1875d9de2d3SDavid du Colombier 				a->cmdline[n] = 0;
1885d9de2d3SDavid du Colombier 			else
1895d9de2d3SDavid du Colombier 				BOOTARGS[BOOTARGSLEN-1] = 0;
1905d9de2d3SDavid du Colombier 			plan9iniinit(a->cmdline, 1);
1915d9de2d3SDavid du Colombier 			break;
1925d9de2d3SDavid du Colombier 		}
1935d9de2d3SDavid du Colombier 		a = (Atag*)((u32int*)a + a->size);
1945d9de2d3SDavid du Colombier 	}
1955d9de2d3SDavid du Colombier }
1965d9de2d3SDavid du Colombier 
197*5c47fe09SDavid du Colombier /* enable scheduling of this cpu */
198*5c47fe09SDavid du Colombier void
machon(uint cpu)199*5c47fe09SDavid du Colombier machon(uint cpu)
200*5c47fe09SDavid du Colombier {
201*5c47fe09SDavid du Colombier 	ulong cpubit;
202*5c47fe09SDavid du Colombier 
203*5c47fe09SDavid du Colombier 	cpubit = 1 << cpu;
204*5c47fe09SDavid du Colombier 	lock(&active);
205*5c47fe09SDavid du Colombier 	if ((active.machs & cpubit) == 0) {	/* currently off? */
206*5c47fe09SDavid du Colombier 		conf.nmach++;
207*5c47fe09SDavid du Colombier 		active.machs |= cpubit;
208*5c47fe09SDavid du Colombier 	}
209*5c47fe09SDavid du Colombier 	unlock(&active);
210*5c47fe09SDavid du Colombier }
211*5c47fe09SDavid du Colombier 
212*5c47fe09SDavid du Colombier /* disable scheduling of this cpu */
213*5c47fe09SDavid du Colombier void
machoff(uint cpu)214*5c47fe09SDavid du Colombier machoff(uint cpu)
215*5c47fe09SDavid du Colombier {
216*5c47fe09SDavid du Colombier 	ulong cpubit;
217*5c47fe09SDavid du Colombier 
218*5c47fe09SDavid du Colombier 	cpubit = 1 << cpu;
219*5c47fe09SDavid du Colombier 	lock(&active);
220*5c47fe09SDavid du Colombier 	if (active.machs & cpubit) {		/* currently on? */
221*5c47fe09SDavid du Colombier 		conf.nmach--;
222*5c47fe09SDavid du Colombier 		active.machs &= ~cpubit;
223*5c47fe09SDavid du Colombier 	}
224*5c47fe09SDavid du Colombier 	unlock(&active);
225*5c47fe09SDavid du Colombier }
226*5c47fe09SDavid du Colombier 
2275d9de2d3SDavid du Colombier void
machinit(void)2285d9de2d3SDavid du Colombier machinit(void)
2295d9de2d3SDavid du Colombier {
230*5c47fe09SDavid du Colombier 	Mach *m0;
2315d9de2d3SDavid du Colombier 
2325d9de2d3SDavid du Colombier 	m->ticks = 1;
2335d9de2d3SDavid du Colombier 	m->perf.period = 1;
234*5c47fe09SDavid du Colombier 	m0 = MACHP(0);
235*5c47fe09SDavid du Colombier 	if (m->machno != 0) {
236*5c47fe09SDavid du Colombier 		/* synchronise with cpu 0 */
237*5c47fe09SDavid du Colombier 		m->ticks = m0->ticks;
238*5c47fe09SDavid du Colombier 	}
239*5c47fe09SDavid du Colombier }
2405d9de2d3SDavid du Colombier 
241*5c47fe09SDavid du Colombier void
mach0init(void)242*5c47fe09SDavid du Colombier mach0init(void)
243*5c47fe09SDavid du Colombier {
244*5c47fe09SDavid du Colombier 	conf.nmach = 0;
2455d9de2d3SDavid du Colombier 
246*5c47fe09SDavid du Colombier 	m->machno = 0;
247*5c47fe09SDavid du Colombier 	machaddr[m->machno] = m;
248*5c47fe09SDavid du Colombier 
249*5c47fe09SDavid du Colombier 	machinit();
2505d9de2d3SDavid du Colombier 	active.exiting = 0;
2515d9de2d3SDavid du Colombier 
2525d9de2d3SDavid du Colombier 	up = nil;
2535d9de2d3SDavid du Colombier }
2545d9de2d3SDavid du Colombier 
255*5c47fe09SDavid du Colombier void
launchinit(int ncpus)256*5c47fe09SDavid du Colombier launchinit(int ncpus)
257*5c47fe09SDavid du Colombier {
258*5c47fe09SDavid du Colombier 	int mach;
259*5c47fe09SDavid du Colombier 	Mach *mm;
260*5c47fe09SDavid du Colombier 	PTE *l1;
261*5c47fe09SDavid du Colombier 
262*5c47fe09SDavid du Colombier 	if(ncpus > MAXMACH)
263*5c47fe09SDavid du Colombier 		ncpus = MAXMACH;
264*5c47fe09SDavid du Colombier 	for(mach = 1; mach < ncpus; mach++){
265*5c47fe09SDavid du Colombier 		machaddr[mach] = mm = mallocalign(MACHSIZE, MACHSIZE, 0, 0);
266*5c47fe09SDavid du Colombier 		l1 = mallocalign(L1SIZE, L1SIZE, 0, 0);
267*5c47fe09SDavid du Colombier 		if(mm == nil || l1 == nil)
268*5c47fe09SDavid du Colombier 			panic("launchinit");
269*5c47fe09SDavid du Colombier 		memset(mm, 0, MACHSIZE);
270*5c47fe09SDavid du Colombier 		mm->machno = mach;
271*5c47fe09SDavid du Colombier 
272*5c47fe09SDavid du Colombier 		memmove(l1, m->mmul1, L1SIZE);  /* clone cpu0's l1 table */
273*5c47fe09SDavid du Colombier 		cachedwbse(l1, L1SIZE);
274*5c47fe09SDavid du Colombier 		mm->mmul1 = l1;
275*5c47fe09SDavid du Colombier 		cachedwbse(mm, MACHSIZE);
276*5c47fe09SDavid du Colombier 
277*5c47fe09SDavid du Colombier 	}
278*5c47fe09SDavid du Colombier 	cachedwbse(machaddr, sizeof machaddr);
279*5c47fe09SDavid du Colombier 	if((mach = startcpus(ncpus)) < ncpus)
280*5c47fe09SDavid du Colombier 			print("only %d cpu%s started\n", mach, mach == 1? "" : "s");
281*5c47fe09SDavid du Colombier }
282*5c47fe09SDavid du Colombier 
2835d9de2d3SDavid du Colombier static void
optionsinit(char * s)2845d9de2d3SDavid du Colombier optionsinit(char* s)
2855d9de2d3SDavid du Colombier {
2865d9de2d3SDavid du Colombier 	strecpy(oargb, oargb+sizeof(oargb), s);
2875d9de2d3SDavid du Colombier 
2885d9de2d3SDavid du Colombier 	oargblen = strlen(oargb);
2895d9de2d3SDavid du Colombier 	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
2905d9de2d3SDavid du Colombier 	oargv[oargc] = nil;
2915d9de2d3SDavid du Colombier }
2925d9de2d3SDavid du Colombier 
2935d9de2d3SDavid du Colombier void
main(void)2945d9de2d3SDavid du Colombier main(void)
2955d9de2d3SDavid du Colombier {
2965d9de2d3SDavid du Colombier 	extern char edata[], end[];
297*5c47fe09SDavid du Colombier 	uint fw, board;
2985d9de2d3SDavid du Colombier 
2995d9de2d3SDavid du Colombier 	m = (Mach*)MACHADDR;
3005d9de2d3SDavid du Colombier 	memset(edata, 0, end - edata);	/* clear bss */
301*5c47fe09SDavid du Colombier 	mach0init();
302*5c47fe09SDavid du Colombier 	m->mmul1 = (PTE*)L1;
303*5c47fe09SDavid du Colombier 	machon(0);
3045d9de2d3SDavid du Colombier 
3055d9de2d3SDavid du Colombier 	optionsinit("/boot/boot boot");
3065d9de2d3SDavid du Colombier 	quotefmtinstall();
3075d9de2d3SDavid du Colombier 
3085d9de2d3SDavid du Colombier 	ataginit((Atag*)BOOTARGS);
3095d9de2d3SDavid du Colombier 	confinit();		/* figures out amount of memory */
3105d9de2d3SDavid du Colombier 	xinit();
3115d9de2d3SDavid du Colombier 	uartconsinit();
3125d9de2d3SDavid du Colombier 	screeninit();
3135d9de2d3SDavid du Colombier 
3145d9de2d3SDavid du Colombier 	print("\nPlan 9 from Bell Labs\n");
315*5c47fe09SDavid du Colombier 	board = getboardrev();
316*5c47fe09SDavid du Colombier 	fw = getfirmware();
317*5c47fe09SDavid du Colombier 	print("board rev: %#ux firmware rev: %d\n", board, fw);
318*5c47fe09SDavid du Colombier 	if(fw < Minfirmrev){
3193ec63e64SDavid du Colombier 		print("Sorry, firmware (start*.elf) must be at least rev %d"
3203ec63e64SDavid du Colombier 		      " or newer than %s\n", Minfirmrev, Minfirmdate);
3215d9de2d3SDavid du Colombier 		for(;;)
3225d9de2d3SDavid du Colombier 			;
3235d9de2d3SDavid du Colombier 	}
324*5c47fe09SDavid du Colombier 	/* set clock rate to arm_freq from config.txt (default pi1:700Mhz pi2:900MHz) */
325*5c47fe09SDavid du Colombier 	setclkrate(ClkArm, 0);
3265d9de2d3SDavid du Colombier 	trapinit();
3275d9de2d3SDavid du Colombier 	clockinit();
3285d9de2d3SDavid du Colombier 	printinit();
3295d9de2d3SDavid du Colombier 	timersinit();
3305d9de2d3SDavid du Colombier 	if(conf.monitor)
3315d9de2d3SDavid du Colombier 		swcursorinit();
3325d9de2d3SDavid du Colombier 	cpuidprint();
333*5c47fe09SDavid du Colombier 	print("clocks: CPU %lud core %lud UART %lud EMMC %lud\n",
334*5c47fe09SDavid du Colombier 		getclkrate(ClkArm), getclkrate(ClkCore), getclkrate(ClkUart), getclkrate(ClkEmmc));
3355d9de2d3SDavid du Colombier 	archreset();
336*5c47fe09SDavid du Colombier 	vgpinit();
3375d9de2d3SDavid du Colombier 
3385d9de2d3SDavid du Colombier 	procinit0();
3395d9de2d3SDavid du Colombier 	initseg();
3405d9de2d3SDavid du Colombier 	links();
3415d9de2d3SDavid du Colombier 	chandevreset();			/* most devices are discovered here */
3425d9de2d3SDavid du Colombier 	pageinit();
3435d9de2d3SDavid du Colombier 	swapinit();
3445d9de2d3SDavid du Colombier 	userinit();
345*5c47fe09SDavid du Colombier 	launchinit(getncpus());
346*5c47fe09SDavid du Colombier 	mmuinit1();
347*5c47fe09SDavid du Colombier 
3485d9de2d3SDavid du Colombier 	schedinit();
3495d9de2d3SDavid du Colombier 	assert(0);			/* shouldn't have returned */
3505d9de2d3SDavid du Colombier }
3515d9de2d3SDavid du Colombier 
3525d9de2d3SDavid du Colombier /*
3535d9de2d3SDavid du Colombier  *  starting place for first process
3545d9de2d3SDavid du Colombier  */
3555d9de2d3SDavid du Colombier void
init0(void)3565d9de2d3SDavid du Colombier init0(void)
3575d9de2d3SDavid du Colombier {
3585d9de2d3SDavid du Colombier 	int i;
359*5c47fe09SDavid du Colombier 	Chan *c;
3605d9de2d3SDavid du Colombier 	char buf[2*KNAMELEN];
3615d9de2d3SDavid du Colombier 
3625d9de2d3SDavid du Colombier 	up->nerrlab = 0;
3635d9de2d3SDavid du Colombier 	coherence();
3645d9de2d3SDavid du Colombier 	spllo();
3655d9de2d3SDavid du Colombier 
3665d9de2d3SDavid du Colombier 	/*
3675d9de2d3SDavid du Colombier 	 * These are o.k. because rootinit is null.
3685d9de2d3SDavid du Colombier 	 * Then early kproc's will have a root and dot.
3695d9de2d3SDavid du Colombier 	 */
3705d9de2d3SDavid du Colombier 	up->slash = namec("#/", Atodir, 0, 0);
3715d9de2d3SDavid du Colombier 	pathclose(up->slash->path);
3725d9de2d3SDavid du Colombier 	up->slash->path = newpath("/");
3735d9de2d3SDavid du Colombier 	up->dot = cclone(up->slash);
3745d9de2d3SDavid du Colombier 
3755d9de2d3SDavid du Colombier 	chandevinit();
3765d9de2d3SDavid du Colombier 
3775d9de2d3SDavid du Colombier 	if(!waserror()){
3785d9de2d3SDavid du Colombier 		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
3795d9de2d3SDavid du Colombier 		ksetenv("terminal", buf, 0);
3805d9de2d3SDavid du Colombier 		ksetenv("cputype", "arm", 0);
3815d9de2d3SDavid du Colombier 		if(cpuserver)
3825d9de2d3SDavid du Colombier 			ksetenv("service", "cpu", 0);
3835d9de2d3SDavid du Colombier 		else
3845d9de2d3SDavid du Colombier 			ksetenv("service", "terminal", 0);
3855d9de2d3SDavid du Colombier 		snprint(buf, sizeof(buf), "-a %s", getethermac());
3865d9de2d3SDavid du Colombier 		ksetenv("etherargs", buf, 0);
3875d9de2d3SDavid du Colombier 
3885d9de2d3SDavid du Colombier 		/* convert plan9.ini variables to #e and #ec */
3895d9de2d3SDavid du Colombier 		for(i = 0; i < nconf; i++) {
3905d9de2d3SDavid du Colombier 			ksetenv(confname[i], confval[i], 0);
3915d9de2d3SDavid du Colombier 			ksetenv(confname[i], confval[i], 1);
3925d9de2d3SDavid du Colombier 		}
393*5c47fe09SDavid du Colombier 		if(getconf("pitft")){
394*5c47fe09SDavid du Colombier 			c = namec("#P/pitft", Aopen, OWRITE, 0);
395*5c47fe09SDavid du Colombier 			if(!waserror()){
396*5c47fe09SDavid du Colombier 				devtab[c->type]->write(c, "init", 4, 0);
397*5c47fe09SDavid du Colombier 				poperror();
398*5c47fe09SDavid du Colombier 			}
399*5c47fe09SDavid du Colombier 			cclose(c);
400*5c47fe09SDavid du Colombier 		}
4015d9de2d3SDavid du Colombier 		poperror();
4025d9de2d3SDavid du Colombier 	}
4035d9de2d3SDavid du Colombier 	kproc("alarm", alarmkproc, 0);
4045d9de2d3SDavid du Colombier 	touser(sp);
4055d9de2d3SDavid du Colombier 	assert(0);			/* shouldn't have returned */
4065d9de2d3SDavid du Colombier }
4075d9de2d3SDavid du Colombier 
4085d9de2d3SDavid du Colombier static void
bootargs(uintptr base)4095d9de2d3SDavid du Colombier bootargs(uintptr base)
4105d9de2d3SDavid du Colombier {
4115d9de2d3SDavid du Colombier 	int i;
4125d9de2d3SDavid du Colombier 	ulong ssize;
4135d9de2d3SDavid du Colombier 	char **av, *p;
4145d9de2d3SDavid du Colombier 
4155d9de2d3SDavid du Colombier 	/*
4165d9de2d3SDavid du Colombier 	 * Push the boot args onto the stack.
4175d9de2d3SDavid du Colombier 	 * The initial value of the user stack must be such
4185d9de2d3SDavid du Colombier 	 * that the total used is larger than the maximum size
4195d9de2d3SDavid du Colombier 	 * of the argument list checked in syscall.
4205d9de2d3SDavid du Colombier 	 */
4215d9de2d3SDavid du Colombier 	i = oargblen+1;
42223a96966SDavid du Colombier 	p = UINT2PTR(STACKALIGN(base + BY2PG - Ustkheadroom - i));
4235d9de2d3SDavid du Colombier 	memmove(p, oargb, i);
4245d9de2d3SDavid du Colombier 
4255d9de2d3SDavid du Colombier 	/*
4265d9de2d3SDavid du Colombier 	 * Now push the argv pointers.
4275d9de2d3SDavid du Colombier 	 * The code jumped to by touser in lproc.s expects arguments
4285d9de2d3SDavid du Colombier 	 *	main(char* argv0, ...)
4295d9de2d3SDavid du Colombier 	 * and calls
4305d9de2d3SDavid du Colombier 	 * 	startboot("/boot/boot", &argv0)
4315d9de2d3SDavid du Colombier 	 * not the usual (int argc, char* argv[])
4325d9de2d3SDavid du Colombier 	 */
4335d9de2d3SDavid du Colombier 	av = (char**)(p - (oargc+1)*sizeof(char*));
4345d9de2d3SDavid du Colombier 	ssize = base + BY2PG - PTR2UINT(av);
4355d9de2d3SDavid du Colombier 	for(i = 0; i < oargc; i++)
4365d9de2d3SDavid du Colombier 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
4375d9de2d3SDavid du Colombier 	*av = nil;
4385d9de2d3SDavid du Colombier 	sp = USTKTOP - ssize;
4395d9de2d3SDavid du Colombier }
4405d9de2d3SDavid du Colombier 
4415d9de2d3SDavid du Colombier /*
4425d9de2d3SDavid du Colombier  *  create the first process
4435d9de2d3SDavid du Colombier  */
4445d9de2d3SDavid du Colombier void
userinit(void)4455d9de2d3SDavid du Colombier userinit(void)
4465d9de2d3SDavid du Colombier {
4475d9de2d3SDavid du Colombier 	Proc *p;
4485d9de2d3SDavid du Colombier 	Segment *s;
4495d9de2d3SDavid du Colombier 	KMap *k;
4505d9de2d3SDavid du Colombier 	Page *pg;
4515d9de2d3SDavid du Colombier 
4525d9de2d3SDavid du Colombier 	/* no processes yet */
4535d9de2d3SDavid du Colombier 	up = nil;
4545d9de2d3SDavid du Colombier 
4555d9de2d3SDavid du Colombier 	p = newproc();
4565d9de2d3SDavid du Colombier 	p->pgrp = newpgrp();
4575d9de2d3SDavid du Colombier 	p->egrp = smalloc(sizeof(Egrp));
4585d9de2d3SDavid du Colombier 	p->egrp->ref = 1;
4595d9de2d3SDavid du Colombier 	p->fgrp = dupfgrp(nil);
4605d9de2d3SDavid du Colombier 	p->rgrp = newrgrp();
4615d9de2d3SDavid du Colombier 	p->procmode = 0640;
4625d9de2d3SDavid du Colombier 
4635d9de2d3SDavid du Colombier 	kstrdup(&eve, "");
4645d9de2d3SDavid du Colombier 	kstrdup(&p->text, "*init*");
4655d9de2d3SDavid du Colombier 	kstrdup(&p->user, eve);
4665d9de2d3SDavid du Colombier 
4675d9de2d3SDavid du Colombier 	/*
4685d9de2d3SDavid du Colombier 	 * Kernel Stack
4695d9de2d3SDavid du Colombier 	 */
4705d9de2d3SDavid du Colombier 	p->sched.pc = PTR2UINT(init0);
4715d9de2d3SDavid du Colombier 	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
4725d9de2d3SDavid du Colombier 	p->sched.sp = STACKALIGN(p->sched.sp);
4735d9de2d3SDavid du Colombier 
4745d9de2d3SDavid du Colombier 	/*
4755d9de2d3SDavid du Colombier 	 * User Stack
4765d9de2d3SDavid du Colombier 	 *
4775d9de2d3SDavid du Colombier 	 * Technically, newpage can't be called here because it
4785d9de2d3SDavid du Colombier 	 * should only be called when in a user context as it may
4795d9de2d3SDavid du Colombier 	 * try to sleep if there are no pages available, but that
4805d9de2d3SDavid du Colombier 	 * shouldn't be the case here.
4815d9de2d3SDavid du Colombier 	 */
4825d9de2d3SDavid du Colombier 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
4835d9de2d3SDavid du Colombier 	s->flushme++;
4845d9de2d3SDavid du Colombier 	p->seg[SSEG] = s;
4855d9de2d3SDavid du Colombier 	pg = newpage(1, 0, USTKTOP-BY2PG);
4865d9de2d3SDavid du Colombier 	segpage(s, pg);
4875d9de2d3SDavid du Colombier 	k = kmap(pg);
4885d9de2d3SDavid du Colombier 	bootargs(VA(k));
4895d9de2d3SDavid du Colombier 	kunmap(k);
4905d9de2d3SDavid du Colombier 
4915d9de2d3SDavid du Colombier 	/*
4925d9de2d3SDavid du Colombier 	 * Text
4935d9de2d3SDavid du Colombier 	 */
4945d9de2d3SDavid du Colombier 	s = newseg(SG_TEXT, UTZERO, 1);
4955d9de2d3SDavid du Colombier 	p->seg[TSEG] = s;
4965d9de2d3SDavid du Colombier 	pg = newpage(1, 0, UTZERO);
4975d9de2d3SDavid du Colombier 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
4985d9de2d3SDavid du Colombier 	segpage(s, pg);
4995d9de2d3SDavid du Colombier 	k = kmap(s->map[0]->pages[0]);
5005d9de2d3SDavid du Colombier 	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
5015d9de2d3SDavid du Colombier 	kunmap(k);
5025d9de2d3SDavid du Colombier 
5035d9de2d3SDavid du Colombier 	ready(p);
5045d9de2d3SDavid du Colombier }
5055d9de2d3SDavid du Colombier 
5065d9de2d3SDavid du Colombier void
confinit(void)5075d9de2d3SDavid du Colombier confinit(void)
5085d9de2d3SDavid du Colombier {
509*5c47fe09SDavid du Colombier 	int i, userpcnt;
5105d9de2d3SDavid du Colombier 	ulong kpages;
5115d9de2d3SDavid du Colombier 	uintptr pa;
5125d9de2d3SDavid du Colombier 	char *p;
5135d9de2d3SDavid du Colombier 
5145d9de2d3SDavid du Colombier 	if(0 && (p = getconf("service")) != nil){
5155d9de2d3SDavid du Colombier 		if(strcmp(p, "cpu") == 0)
5165d9de2d3SDavid du Colombier 			cpuserver = 1;
5175d9de2d3SDavid du Colombier 		else if(strcmp(p,"terminal") == 0)
5185d9de2d3SDavid du Colombier 			cpuserver = 0;
5195d9de2d3SDavid du Colombier 	}
5205d9de2d3SDavid du Colombier 	if((p = getconf("*maxmem")) != nil){
5215d9de2d3SDavid du Colombier 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
5225d9de2d3SDavid du Colombier 		if (memsize < 16*MB)		/* sanity */
5235d9de2d3SDavid du Colombier 			memsize = 16*MB;
5245d9de2d3SDavid du Colombier 	}
5255d9de2d3SDavid du Colombier 
5265d9de2d3SDavid du Colombier 	getramsize(&conf.mem[0]);
5275d9de2d3SDavid du Colombier 	if(conf.mem[0].limit == 0){
5285d9de2d3SDavid du Colombier 		conf.mem[0].base = PHYSDRAM;
5295d9de2d3SDavid du Colombier 		conf.mem[0].limit = PHYSDRAM + memsize;
530*5c47fe09SDavid du Colombier 	}
531*5c47fe09SDavid du Colombier 	/*
532*5c47fe09SDavid du Colombier 	 * pi4 extra memory (beyond video ram) indicated by board id
533*5c47fe09SDavid du Colombier 	 */
534*5c47fe09SDavid du Colombier 	switch(getboardrev()&0xF00000){
535*5c47fe09SDavid du Colombier 	case 0xA00000:
536*5c47fe09SDavid du Colombier 		break;
537*5c47fe09SDavid du Colombier 	case 0xB00000:
538*5c47fe09SDavid du Colombier 		conf.mem[1].base = 1*GiB;
539*5c47fe09SDavid du Colombier 		conf.mem[1].limit = 2*GiB;
540*5c47fe09SDavid du Colombier 		break;
541*5c47fe09SDavid du Colombier 	case 0xC00000:
542*5c47fe09SDavid du Colombier 		conf.mem[1].base = 1*GiB;
543*5c47fe09SDavid du Colombier 		conf.mem[1].limit = 0xFFF00000;
544*5c47fe09SDavid du Colombier 		break;
545*5c47fe09SDavid du Colombier 	case 0xD00000:
546*5c47fe09SDavid du Colombier 		conf.mem[1].base = 1*GiB;
547*5c47fe09SDavid du Colombier 		conf.mem[1].limit = 0xFFF00000;
548*5c47fe09SDavid du Colombier 		break;
549*5c47fe09SDavid du Colombier 	}
550*5c47fe09SDavid du Colombier 	if(conf.mem[1].limit > soc.dramsize)
551*5c47fe09SDavid du Colombier 		conf.mem[1].limit = soc.dramsize;
552*5c47fe09SDavid du Colombier 	if(p != nil){
553*5c47fe09SDavid du Colombier 		if(memsize < conf.mem[0].limit){
554*5c47fe09SDavid du Colombier 			conf.mem[0].limit = memsize;
555*5c47fe09SDavid du Colombier 			conf.mem[1].limit = 0;
556*5c47fe09SDavid du Colombier 		}else if(memsize >= conf.mem[1].base && memsize < conf.mem[1].limit)
557*5c47fe09SDavid du Colombier 			conf.mem[1].limit = memsize;
558*5c47fe09SDavid du Colombier 	}
559*5c47fe09SDavid du Colombier 
560*5c47fe09SDavid du Colombier 	if(p = getconf("*kernelpercent"))
561*5c47fe09SDavid du Colombier 		userpcnt = 100 - strtol(p, 0, 0);
562*5c47fe09SDavid du Colombier 	else
563*5c47fe09SDavid du Colombier 		userpcnt = 0;
5645d9de2d3SDavid du Colombier 
5655d9de2d3SDavid du Colombier 	conf.npage = 0;
5665d9de2d3SDavid du Colombier 	pa = PADDR(PGROUND(PTR2UINT(end)));
5675d9de2d3SDavid du Colombier 
5685d9de2d3SDavid du Colombier 	/*
5695d9de2d3SDavid du Colombier 	 *  we assume that the kernel is at the beginning of one of the
5705d9de2d3SDavid du Colombier 	 *  contiguous chunks of memory and fits therein.
5715d9de2d3SDavid du Colombier 	 */
5725d9de2d3SDavid du Colombier 	for(i=0; i<nelem(conf.mem); i++){
5735d9de2d3SDavid du Colombier 		/* take kernel out of allocatable space */
5745d9de2d3SDavid du Colombier 		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
5755d9de2d3SDavid du Colombier 			conf.mem[i].base = pa;
5765d9de2d3SDavid du Colombier 
5775d9de2d3SDavid du Colombier 		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
5785d9de2d3SDavid du Colombier 		conf.npage += conf.mem[i].npage;
5795d9de2d3SDavid du Colombier 	}
5805d9de2d3SDavid du Colombier 
581*5c47fe09SDavid du Colombier 	if(userpcnt < 10 || userpcnt > 99)
582*5c47fe09SDavid du Colombier 		userpcnt = 90;
583*5c47fe09SDavid du Colombier 	conf.upages = (conf.npage*userpcnt)/100;
584*5c47fe09SDavid du Colombier 	if(conf.npage - conf.upages > 256*MiB/BY2PG)
585*5c47fe09SDavid du Colombier 		conf.upages = conf.npage - 256*MiB/BY2PG;
5865d9de2d3SDavid du Colombier 	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
5875d9de2d3SDavid du Colombier 
5885d9de2d3SDavid du Colombier 	/* set up other configuration parameters */
5895d9de2d3SDavid du Colombier 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
5905d9de2d3SDavid du Colombier 	if(cpuserver)
5915d9de2d3SDavid du Colombier 		conf.nproc *= 3;
5925d9de2d3SDavid du Colombier 	if(conf.nproc > 2000)
5935d9de2d3SDavid du Colombier 		conf.nproc = 2000;
5945d9de2d3SDavid du Colombier 	conf.nswap = conf.npage*3;
5955d9de2d3SDavid du Colombier 	conf.nswppo = 4096;
5965d9de2d3SDavid du Colombier 	conf.nimage = 200;
5975d9de2d3SDavid du Colombier 
598*5c47fe09SDavid du Colombier 	conf.copymode = 1;		/* copy on reference, not copy on write */
5995d9de2d3SDavid du Colombier 
6005d9de2d3SDavid du Colombier 	/*
6015d9de2d3SDavid du Colombier 	 * Guess how much is taken by the large permanent
6025d9de2d3SDavid du Colombier 	 * datastructures. Mntcache and Mntrpc are not accounted for
6035d9de2d3SDavid du Colombier 	 * (probably ~300KB).
6045d9de2d3SDavid du Colombier 	 */
6055d9de2d3SDavid du Colombier 	kpages = conf.npage - conf.upages;
6065d9de2d3SDavid du Colombier 	kpages *= BY2PG;
6075d9de2d3SDavid du Colombier 	kpages -= conf.upages*sizeof(Page)
6085d9de2d3SDavid du Colombier 		+ conf.nproc*sizeof(Proc)
6095d9de2d3SDavid du Colombier 		+ conf.nimage*sizeof(Image)
6105d9de2d3SDavid du Colombier 		+ conf.nswap
6110a96a064SDavid du Colombier 		+ conf.nswppo*sizeof(Page*);
6125d9de2d3SDavid du Colombier 	mainmem->maxsize = kpages;
6135d9de2d3SDavid du Colombier 	if(!cpuserver)
6145d9de2d3SDavid du Colombier 		/*
6155d9de2d3SDavid du Colombier 		 * give terminals lots of image memory, too; the dynamic
6165d9de2d3SDavid du Colombier 		 * allocation will balance the load properly, hopefully.
6175d9de2d3SDavid du Colombier 		 * be careful with 32-bit overflow.
6185d9de2d3SDavid du Colombier 		 */
6195d9de2d3SDavid du Colombier 		imagmem->maxsize = kpages;
6205d9de2d3SDavid du Colombier 
6215d9de2d3SDavid du Colombier }
6225d9de2d3SDavid du Colombier 
6235d9de2d3SDavid du Colombier static void
shutdown(int ispanic)6245d9de2d3SDavid du Colombier shutdown(int ispanic)
6255d9de2d3SDavid du Colombier {
6265d9de2d3SDavid du Colombier 	int ms, once;
6275d9de2d3SDavid du Colombier 
6285d9de2d3SDavid du Colombier 	lock(&active);
6295d9de2d3SDavid du Colombier 	if(ispanic)
6305d9de2d3SDavid du Colombier 		active.ispanic = ispanic;
6315d9de2d3SDavid du Colombier 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
6325d9de2d3SDavid du Colombier 		active.ispanic = 0;
6335d9de2d3SDavid du Colombier 	once = active.machs & (1<<m->machno);
6345d9de2d3SDavid du Colombier 	active.machs &= ~(1<<m->machno);
6355d9de2d3SDavid du Colombier 	active.exiting = 1;
6365d9de2d3SDavid du Colombier 	unlock(&active);
6375d9de2d3SDavid du Colombier 
638*5c47fe09SDavid du Colombier 	if(once) {
639*5c47fe09SDavid du Colombier 		delay(m->machno*100);		/* stagger them */
6405d9de2d3SDavid du Colombier 		iprint("cpu%d: exiting\n", m->machno);
641*5c47fe09SDavid du Colombier 	}
6425d9de2d3SDavid du Colombier 	spllo();
643*5c47fe09SDavid du Colombier 	if (m->machno == 0)
644*5c47fe09SDavid du Colombier 		ms = 5*1000;
645*5c47fe09SDavid du Colombier 	else
646*5c47fe09SDavid du Colombier 		ms = 2*1000;
647*5c47fe09SDavid du Colombier 	for(; ms > 0; ms -= TK2MS(2)){
6485d9de2d3SDavid du Colombier 		delay(TK2MS(2));
6495d9de2d3SDavid du Colombier 		if(active.machs == 0 && consactive() == 0)
6505d9de2d3SDavid du Colombier 			break;
6515d9de2d3SDavid du Colombier 	}
652*5c47fe09SDavid du Colombier 	if(active.ispanic){
653*5c47fe09SDavid du Colombier 		if(!cpuserver)
654*5c47fe09SDavid du Colombier 			for(;;)
655*5c47fe09SDavid du Colombier 				;
656*5c47fe09SDavid du Colombier 		if(getconf("*debug"))
657*5c47fe09SDavid du Colombier 			delay(5*60*1000);
658*5c47fe09SDavid du Colombier 		else
659*5c47fe09SDavid du Colombier 			delay(10000);
660*5c47fe09SDavid du Colombier 	}
6615d9de2d3SDavid du Colombier }
6625d9de2d3SDavid du Colombier 
6635d9de2d3SDavid du Colombier /*
6645d9de2d3SDavid du Colombier  *  exit kernel either on a panic or user request
6655d9de2d3SDavid du Colombier  */
6665d9de2d3SDavid du Colombier void
exit(int code)6675d9de2d3SDavid du Colombier exit(int code)
6685d9de2d3SDavid du Colombier {
669*5c47fe09SDavid du Colombier 	void (*f)(ulong, ulong, ulong);
670*5c47fe09SDavid du Colombier 
6715d9de2d3SDavid du Colombier 	shutdown(code);
6725d9de2d3SDavid du Colombier 	splfhi();
673*5c47fe09SDavid du Colombier 	if(m->machno == 0)
6745d9de2d3SDavid du Colombier 		archreboot();
675*5c47fe09SDavid du Colombier 	else{
676*5c47fe09SDavid du Colombier 		f = (void*)REBOOTADDR;
677*5c47fe09SDavid du Colombier 		intrcpushutdown();
678*5c47fe09SDavid du Colombier 		memmove(f, rebootcode, sizeof(rebootcode));
679*5c47fe09SDavid du Colombier 		cachedwbse(f, sizeof(rebootcode));
680*5c47fe09SDavid du Colombier 		cacheiinvse(f, sizeof(rebootcode));
681*5c47fe09SDavid du Colombier 		(*f)(0, soc.armlocal, 0);
682*5c47fe09SDavid du Colombier 		for(;;){}
683*5c47fe09SDavid du Colombier 	}
6845d9de2d3SDavid du Colombier }
6855d9de2d3SDavid du Colombier 
6865d9de2d3SDavid du Colombier /*
6875d9de2d3SDavid du Colombier  * stub for ../omap/devether.c
6885d9de2d3SDavid du Colombier  */
6895d9de2d3SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)6905d9de2d3SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
6915d9de2d3SDavid du Colombier {
692*5c47fe09SDavid du Colombier 	char cc[32], *p;
693*5c47fe09SDavid du Colombier 	int i;
694*5c47fe09SDavid du Colombier 
695*5c47fe09SDavid du Colombier 	if(strcmp(class, "ether") != 0)
696*5c47fe09SDavid du Colombier 		return 0;
697*5c47fe09SDavid du Colombier 	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
698*5c47fe09SDavid du Colombier 	p = getconf(cc);
699*5c47fe09SDavid du Colombier 	if(p == nil)
700*5c47fe09SDavid du Colombier 		return (ctlrno == 0);
701*5c47fe09SDavid du Colombier 	isa->type = "";
702*5c47fe09SDavid du Colombier 	isa->nopt = tokenize(p, isa->opt, NISAOPT);
703*5c47fe09SDavid du Colombier 	for(i = 0; i < isa->nopt; i++){
704*5c47fe09SDavid du Colombier 		p = isa->opt[i];
705*5c47fe09SDavid du Colombier 		if(cistrncmp(p, "type=", 5) == 0)
706*5c47fe09SDavid du Colombier 			isa->type = p + 5;
707*5c47fe09SDavid du Colombier 	}
708*5c47fe09SDavid du Colombier 	return 1;
7095d9de2d3SDavid du Colombier }
7105d9de2d3SDavid du Colombier 
7115d9de2d3SDavid du Colombier /*
7125d9de2d3SDavid du Colombier  * the new kernel is already loaded at address `code'
7135d9de2d3SDavid du Colombier  * of size `size' and entry point `entry'.
7145d9de2d3SDavid du Colombier  */
7155d9de2d3SDavid du Colombier void
reboot(void * entry,void * code,ulong size)7165d9de2d3SDavid du Colombier reboot(void *entry, void *code, ulong size)
7175d9de2d3SDavid du Colombier {
7185d9de2d3SDavid du Colombier 	void (*f)(ulong, ulong, ulong);
7195d9de2d3SDavid du Colombier 
7205d9de2d3SDavid du Colombier 	writeconf();
721*5c47fe09SDavid du Colombier 
722*5c47fe09SDavid du Colombier 	/*
723*5c47fe09SDavid du Colombier 	 * the boot processor is cpu0.  execute this function on it
724*5c47fe09SDavid du Colombier 	 * so that the new kernel has the same cpu0.
725*5c47fe09SDavid du Colombier 	 */
726*5c47fe09SDavid du Colombier 	if (m->machno != 0) {
727*5c47fe09SDavid du Colombier 		procwired(up, 0);
728*5c47fe09SDavid du Colombier 		sched();
729*5c47fe09SDavid du Colombier 	}
730*5c47fe09SDavid du Colombier 	if (m->machno != 0)
731*5c47fe09SDavid du Colombier 		print("on cpu%d (not 0)!\n", m->machno);
732*5c47fe09SDavid du Colombier 
733*5c47fe09SDavid du Colombier 	/* setup reboot trampoline function */
734*5c47fe09SDavid du Colombier 	f = (void*)REBOOTADDR;
735*5c47fe09SDavid du Colombier 	memmove(f, rebootcode, sizeof(rebootcode));
736*5c47fe09SDavid du Colombier 	cachedwbse(f, sizeof(rebootcode));
737*5c47fe09SDavid du Colombier 
7385d9de2d3SDavid du Colombier 	shutdown(0);
7395d9de2d3SDavid du Colombier 
7405d9de2d3SDavid du Colombier 	/*
7415d9de2d3SDavid du Colombier 	 * should be the only processor running now
7425d9de2d3SDavid du Colombier 	 */
7435d9de2d3SDavid du Colombier 
744*5c47fe09SDavid du Colombier 	delay(500);
7455d9de2d3SDavid du Colombier 	print("reboot entry %#lux code %#lux size %ld\n",
7465d9de2d3SDavid du Colombier 		PADDR(entry), PADDR(code), size);
7475d9de2d3SDavid du Colombier 	delay(100);
7485d9de2d3SDavid du Colombier 
7495d9de2d3SDavid du Colombier 	/* turn off buffered serial console */
7505d9de2d3SDavid du Colombier 	serialoq = nil;
7515d9de2d3SDavid du Colombier 	kprintoq = nil;
7525d9de2d3SDavid du Colombier 	screenputs = nil;
7535d9de2d3SDavid du Colombier 
7545d9de2d3SDavid du Colombier 	/* shutdown devices */
755*5c47fe09SDavid du Colombier 	if(!waserror()){
7565d9de2d3SDavid du Colombier 		chandevshutdown();
757*5c47fe09SDavid du Colombier 		poperror();
758*5c47fe09SDavid du Colombier 	}
7595d9de2d3SDavid du Colombier 
7605d9de2d3SDavid du Colombier 	/* stop the clock (and watchdog if any) */
7615d9de2d3SDavid du Colombier 	clockshutdown();
7625d9de2d3SDavid du Colombier 
7635d9de2d3SDavid du Colombier 	splfhi();
764*5c47fe09SDavid du Colombier 	intrshutdown();
7655d9de2d3SDavid du Colombier 
7665d9de2d3SDavid du Colombier 	/* off we go - never to return */
767*5c47fe09SDavid du Colombier 	cacheuwbinv();
768*5c47fe09SDavid du Colombier 	l2cacheuwbinv();
7695d9de2d3SDavid du Colombier 	(*f)(PADDR(entry), PADDR(code), size);
7705d9de2d3SDavid du Colombier 
7715d9de2d3SDavid du Colombier 	iprint("loaded kernel returned!\n");
7725d9de2d3SDavid du Colombier 	delay(1000);
7735d9de2d3SDavid du Colombier 	archreboot();
7745d9de2d3SDavid du Colombier }
775