plan 9 kernel history: overview | file list | diff list

1992/0812/power/main.c (diff list | history)

power/main.c on 1990/0227
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
#include	"init.h" 
 
1992/0622    
Softtlb stlb[MAXMACH][STLBSIZE];		/* software tlb simulation */ 
int	_argc;					/* args passed by boot process */ 
char 	**_argv; 
char	**_env; 
char 	argbuf[128];				/* arguments passed to initcode */ 
int	argsize; 
char	consname[NAMELEN];			/* environment vars from NVRAM */ 
char	diskless[NAMELEN]; 
char	confbuf[4*1024];			/* config file read by boot program */ 
int	ioid;					/* IO board type */ 
1991/0425    
 
1990/0227    
void 
main(void) 
{ 
1990/0801    
	machinit(); 
1990/0227    
	active.exiting = 0; 
	active.machs = 1; 
1990/0504    
	arginit(); 
1992/0610    
	confinit(); 
1990/0227    
	lockinit(); 
1992/0622    
	xinit(); 
1990/0227    
	printinit(); 
1991/0607    
	duartspecial(0, &printq, &kbdq, 9600); 
1992/0622    
	pageinit(); 
1990/0227    
	tlbinit(); 
	vecinit(); 
	procinit0(); 
1991/0705    
	initseg(); 
1990/0227    
	clockinit(); 
1990/0826    
	ioboardinit(); 
1990/0227    
	chandevreset(); 
	streaminit(); 
1991/0705    
	swapinit(); 
1990/0227    
	userinit(); 
	launchinit(); 
	schedinit(); 
} 
 
void 
machinit(void) 
{ 
	int n; 
 
1990/0801    
	icflush(0, 64*1024); 
1990/0227    
	n = m->machno; 
	memset(m, 0, sizeof(Mach)); 
	m->machno = n; 
1991/0425    
	m->stb = &stlb[n][0]; 
1991/0607    
	duartinit(); 
1992/0509    
 
	m->ledval = 0xff; 
1990/0227    
} 
 
void 
tlbinit(void) 
{ 
	int i; 
 
	for(i=0; i<NTLB; i++) 
		puttlbx(i, KZERO | PTEPID(i), 0); 
} 
 
void 
vecinit(void) 
{ 
	ulong *p, *q; 
	int size; 
 
	p = (ulong*)EXCEPTION; 
	q = (ulong*)vector80; 
	for(size=0; size<4; size++) 
		*p++ = *q++; 
	p = (ulong*)UTLBMISS; 
1991/0425    
	q = (ulong*)vector0; 
1991/0426    
	for(size=0; size<0x80/sizeof(*q); size++) 
1990/0227    
		*p++ = *q++; 
} 
 
/* 
1990/11161    
 *  reset the vme bus 
 */ 
void 
vmereset(void) 
{ 
	int noforce; 
 
	if(ioid >= IO3R1) 
		noforce = 1; 
	else 
		noforce = 0; 
	MODEREG->resetforce = (1<<1) | noforce; 
1991/1105    
	delay(140); 
1990/11161    
	MODEREG->resetforce = noforce; 
} 
 
/* 
1990/0227    
 *  We have to program both the IO2 board to generate interrupts 
 *  and the SBCC on CPU 0 to accept them. 
 */ 
void 
1990/0826    
ioboardinit(void) 
1990/0227    
{ 
	long i; 
1990/0912    
	int maxlevel; 
1990/0826    
 
	ioid = *IOID; 
1990/11161    
	if(ioid >= IO3R1) 
1991/0212    
		maxlevel = 8; 
1990/11161    
	else 
1990/0912    
		maxlevel = 8; 
1990/0911    
 
1990/11161    
	vmereset(); 
1990/0227    
	MODEREG->masterslave = (SLAVE<<4) | MASTER; 
 
	/* 
	 *  all VME interrupts to the error routine 
	 */ 
	for(i=0; i<256; i++) 
		setvmevec(i, novme); 
 
	/* 
1990/0907    
	 *  tell IO2 to sent all interrupts to CPU 0's SBCC 
1990/0227    
	 */ 
1990/0912    
	for(i=0; i<maxlevel; i++) 
1990/0227    
		INTVECREG->i[i].vec = 0<<8; 
 
	/* 
	 *  Tell CPU 0's SBCC to map all interrupts from the IO2 to MIPS level 5 
	 * 
1990/0825    
	 *	0x01		level 0 
	 *	0x02		level 1 
	 *	0x04		level 2 
	 *	0x08		level 4 
	 *	0x10		level 5 
1990/0227    
	 */ 
	SBCCREG->flevel = 0x10; 
 
	/* 
	 *  Tell CPU 0's SBCC to enable all interrupts from the IO2. 
	 * 
	 *  The SBCC 16 bit registers are read/written as ulong, but only 
	 *  bits 23-16 and 7-0 are meaningful. 
	 */ 
1990/0907    
	SBCCREG->fintenable |= 0xff;	  /* allow all interrupts on the IO2 */ 
1990/0227    
	SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */ 
 
	/* 
1991/0212    
	 *  Enable all interrupts on the IO2.  If IO3, run in compatibility mode. 
1990/0227    
	 */ 
1991/0212    
	*IO2SETMASK = 0xff000000; 
1990/1228    
 
} 
 
1990/0227    
void 
launchinit(void) 
{ 
	int i; 
 
	for(i=1; i<conf.nmach; i++) 
		launch(i); 
	for(i=0; i<1000000; i++) 
		if(active.machs == (1<<conf.nmach) - 1){ 
			print("all launched\n"); 
			return; 
		} 
	print("launch: active = %x\n", active.machs); 
} 
 
 
void 
init0(void) 
{ 
	m->proc = u->p; 
	u->p->state = Running; 
	u->p->mach = m; 
	spllo(); 
1990/0427    
 
1991/0315    
	/* 
	 * These are o.k. because rootinit is null. 
	 * Then early kproc's will have a root and dot. 
	 */ 
1990/0227    
	u->slash = (*devtab[0].attach)(0); 
	u->dot = clone(u->slash, 0); 
1991/0315    
	chandevinit(); 
1990/0227    
 
1991/0926    
	if(!waserror()){ 
1991/0927    
		ksetenv("cputype", "mips"); 
1991/1102    
		ksetterm("sgi %s 4D"); 
1991/1101    
		ksetenv("sysname", sysname); 
1991/0926    
		poperror(); 
	} 
1990/0427    
 
1992/0517    
	kproc("alarm", alarmkproc, 0); 
1992/0610    
	touser((uchar*)(USTKTOP - sizeof(argbuf))); 
1990/0227    
} 
 
FPsave	initfp; 
 
void 
userinit(void) 
{ 
	Proc *p; 
1991/0705    
	Segment *s; 
1990/0227    
	User *up; 
1990/0617    
	KMap *k; 
1990/0427    
	char **av; 
1991/0705    
	Page *pg; 
1990/0227    
 
	p = newproc(); 
	p->pgrp = newpgrp(); 
1992/0625    
	p->egrp = smalloc(sizeof(Egrp)); 
	p->egrp->ref = 1; 
	p->fgrp = smalloc(sizeof(Fgrp)); 
	p->fgrp->ref = 1; 
1991/1112    
	p->procmode = 0640; 
1991/0705    
 
1990/0227    
	strcpy(p->text, "*init*"); 
1991/1109    
	strcpy(p->user, eve); 
1990/0227    
	savefpregs(&initfp); 
	p->fpstate = FPinit; 
 
	/* 
	 * Kernel Stack 
	 */ 
	p->sched.pc = (ulong)init0; 
1991/0711    
	p->sched.sp = USERADDR+BY2PG-(1+MAXSYSARG)*BY2WD; 
1991/1222    
	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); 
1990/0227    
 
	/* 
	 * User 
	 */ 
1990/0617    
	k = kmap(p->upage); 
	up = (User*)VA(k); 
1990/0227    
	up->p = p; 
1991/0314    
	up->fpsave.fpstatus = initfp.fpstatus; 
1990/0617    
	kunmap(k); 
1990/0227    
 
	/* 
1990/0427    
	 * User Stack, pass input arguments to boot process 
1990/0227    
	 */ 
1991/0705    
	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); 
	p->seg[SSEG] = s; 
	pg = newpage(1, 0, USTKTOP-BY2PG); 
	segpage(s, pg); 
1992/0610    
	k = kmap(pg); 
	for(av = (char**)argbuf; *av; av++) 
		*av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf; 
	memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf); 
	kunmap(k); 
1991/0705    
 
1990/0227    
	/* 
	 * Text 
	 */ 
1991/0705    
	s = newseg(SG_TEXT, UTZERO, 1); 
	p->seg[TSEG] = s; 
	segpage(s, newpage(1, 0, UTZERO)); 
	k = kmap(s->map[0]->pages[0]); 
1991/0318    
	memmove((ulong*)VA(k), initcode, sizeof initcode); 
1990/0617    
	kunmap(k); 
1990/0227    
 
	ready(p); 
} 
 
void 
lights(int v) 
{ 
 
	*LED = ~v; 
} 
 
typedef struct Beef	Beef; 
struct	Beef 
{ 
	long	deadbeef; 
	long	sum; 
	long	cpuid; 
	long	virid; 
	long	erno; 
	void	(*launch)(void); 
	void	(*rend)(void); 
	long	junk1[4]; 
	long	isize; 
	long	dsize; 
	long	nonbss; 
	long	junk2[18]; 
}; 
 
void 
launch(int n) 
{ 
	Beef *p; 
1990/0912    
	long i, s; 
	ulong *ptr; 
1990/0227    
 
	p = (Beef*) 0xb0000500 + n; 
	p->launch = newstart; 
1990/0912    
	p->sum = 0; 
	s = 0; 
	ptr = (ulong*)p; 
	for (i = 0; i < sizeof(Beef)/sizeof(ulong); i++) 
		s += *ptr++; 
	p->sum = -(s+1); 
 
1990/0227    
	for(i=0; i<3000000; i++) 
		if(p->launch == 0) 
			break; 
} 
 
void 
online(void) 
{ 
 
	machinit(); 
	lock(&active); 
	active.machs |= 1<<m->machno; 
	unlock(&active); 
	tlbinit(); 
	clockinit(); 
	schedinit(); 
} 
 
void 
1992/0812    
exit(int ispanic) 
1990/0227    
{ 
	int i; 
 
1992/0812    
	USED(ispanic); 
1990/0227    
	u = 0; 
	lock(&active); 
	active.machs &= ~(1<<m->machno); 
	active.exiting = 1; 
	unlock(&active); 
	spllo(); 
	print("cpu %d exiting\n", m->machno); 
1991/0705    
	while(active.machs || consactive()) 
1990/0227    
		for(i=0; i<1000; i++) 
			; 
	splhi(); 
	for(i=0; i<2000000; i++) 
		; 
1991/0708    
	duartenable0(); 
1992/0725    
	firmware(cpuserver ? PROM_AUTOBOOT : PROM_REINIT); 
1990/0227    
} 
 
1990/0504    
typedef struct Conftab { 
	char *sym; 
	ulong *x; 
} Conftab; 
 
#include "conf.h" 
 
1990/0227    
Conf	conf; 
 
1990/0504    
ulong 
confeval(char *exp) 
{ 
	char *op; 
	Conftab *ct; 
 
	/* crunch leading white */ 
	while(*exp==' ' || *exp=='\t') 
		exp++; 
 
	op = strchr(exp, '+'); 
	if(op != 0){ 
		*op++ = 0; 
		return confeval(exp) + confeval(op); 
	} 
 
	op = strchr(exp, '*'); 
	if(op != 0){ 
		*op++ = 0; 
		return confeval(exp) * confeval(op); 
	} 
 
	if(*exp >= '0' && *exp <= '9') 
		return strtoul(exp, 0, 0); 
 
	/* crunch trailing white */ 
	op = strchr(exp, ' '); 
	if(op) 
		*op = 0; 
	op = strchr(exp, '\t'); 
	if(op) 
		*op = 0; 
 
	/* lookup in symbol table */ 
	for(ct = conftab; ct->sym; ct++) 
		if(strcmp(exp, ct->sym) == 0) 
			return *(ct->x); 
 
	return 0; 
} 
 
/* 
 *  each line of the configuration is of the form `param = expression'. 
 */ 
1990/0227    
void 
1990/0504    
confset(char *sym) 
1990/0227    
{ 
1990/0504    
	char *val, *p; 
	Conftab *ct; 
1990/0227    
 
1990/0504    
	/* 
 	 *  parse line 
	 */ 
1990/0424    
 
1990/0504    
	/* comment */ 
	if(p = strchr(sym, '#')) 
		*p = 0; 
1990/0227    
 
1990/0504    
	/* skip white */ 
	for(p = sym; *p==' ' || *p=='\t'; p++) 
		; 
	sym = p; 
 
	/* skip sym */ 
	for(; *p && *p!=' ' && *p!='\t' && *p!='='; p++) 
		; 
	if(*p) 
		*p++ = 0; 
 
	/* skip white */ 
	for(; *p==' ' || *p=='\t' || *p=='='; p++) 
		; 
	val = p; 
 
	/* 
	 *  lookup value 
	 */ 
	for(ct = conftab; ct->sym; ct++) 
		if(strcmp(sym, ct->sym) == 0){ 
			*(ct->x) = confeval(val); 
			return; 
		} 
 
	if(strcmp(sym, "sysname")==0){ 
		p = strchr(val, ' '); 
		if(p) 
			*p = 0; 
		strcpy(sysname, val); 
1991/1127    
	} else if(strcmp(sym, "eve")==0){ 
		p = strchr(val, ' '); 
		if(p) 
			*p = 0; 
		strcpy(eve, val); 
1990/0504    
	} 
} 
 
/* 
 *  read the ascii configuration left by the boot kernel 
 */ 
void 
confread(void) 
{ 
	char *line; 
	char *end; 
 
	/* 
	 *  process configuration file 
	 */ 
	line = confbuf; 
	while(end = strchr(line, '\n')){ 
		*end = 0; 
		confset(line); 
		line = end+1; 
	} 
} 
 
void 
confprint(void) 
{ 
	Conftab *ct; 
 
	/* 
	 *  lookup value 
	 */ 
	for(ct = conftab; ct->sym; ct++) 
		print("%s == %d\n", ct->sym, *ct->x); 
} 
 
void 
confinit(void) 
{ 
1992/0711    
	long x, i, *l; 
1992/0715    
	ulong ktop; 
1990/0504    
 
	/* 
	 *  copy configuration down from high memory 
	 */ 
1992/0622    
	strcpy(confbuf, (char *)(0x80000000 + (4*MB) - BY2PG)); 
1990/0504    
 
	/* 
	 *  size memory 
	 */ 
1990/0227    
	x = 0x12345678; 
1990/0322    
	for(i=4; i<128; i+=4){ 
1992/0622    
		l = (long*)(KSEG1|(i*MB)); 
1990/0227    
		*l = x; 
		wbflush(); 
		*(ulong*)KSEG1 = *(ulong*)KSEG1;	/* clear latches */ 
		if(*l != x) 
			break; 
		x += 0x3141526; 
	} 
1990/0614    
	conf.npage0 = i*1024/4; 
1990/1211    
	conf.base0 = 0; 
1990/0614    
	conf.npage = conf.npage0; 
1991/0803    
	conf.npage1 = 0; 
	conf.base1 = 0; 
1992/0715    
 
	ktop = PGROUND((ulong)end); 
	ktop = PADDR(ktop); 
	conf.npage0 -= ktop/BY2PG; 
	conf.base0 += ktop; 
1990/0504    
 
1992/0622    
	conf.upages = (conf.npage*70)/100; 
	i = conf.npage-conf.upages; 
	if(i > (12*MB)/BY2PG) 
		conf.upages +=  i - ((12*MB)/BY2PG); 
1990/0504    
	/* 
1990/0907    
 	 *  clear MP bus error caused by sizing memory 
	 */ 
	i = *SBEADDR; 
1990/1214    
	USED(i); 
1990/0907    
 
	/* 
1990/0504    
	 *  set minimal default values 
	 */ 
1990/1127    
	conf.nmach = 1; 
1992/0101    
	conf.nproc = 100; 
1992/0209    
	conf.nswap = 262144; 
1991/0705    
	conf.nimage = 200; 
1991/0424    
	conf.ipif = 8; 
	conf.ip = 64; 
	conf.arp = 32; 
	conf.frag = 32; 
1990/0430    
 
1990/0504    
	confread(); 
 
	if(conf.nmach > MAXMACH) 
		panic("confinit"); 
 
1991/0705    
	conf.copymode = 1;		/* copy on reference */ 
1990/0504    
} 
 
/* 
 *  copy arguments passed by the boot kernel (or ROM) into a temporary buffer. 
 *  we do this because the arguments are in memory that may be allocated 
 *  to processes or kernel buffers. 
1992/0610    
 * 
 *  also grab any environment variables that might be useful 
1990/0504    
 */ 
1992/0622    
struct 
{ 
1992/0610    
	char	*name; 
	char	*val; 
}bootenv[] = { 
	{"netaddr=",	sysname}, 
	{"console=",	consname}, 
	{"diskless=",	diskless}, 
}; 
char *sp; 
 
char * 
pusharg(char *p) 
{ 
	int n; 
 
	n = strlen(p)+1; 
	sp -= n; 
	memmove(sp, p, n); 
	return sp; 
} 
 
1990/0504    
void 
arginit(void) 
{ 
	int i, n; 
1992/0610    
	char **av; 
1990/0504    
 
1990/0430    
	/* 
1992/0610    
	 *  get boot env variables 
1990/0430    
	 */ 
1992/0610    
	if(*sysname == 0) 
		for(av = _env; *av; av++) 
			for(i=0; i < sizeof bootenv/sizeof bootenv[0]; i++){ 
				n = strlen(bootenv[i].name); 
				if(strncmp(*av, bootenv[i].name, n) == 0){ 
					strncpy(bootenv[i].val, (*av)+n, NAMELEN); 
					bootenv[i].val[NAMELEN-1] = '\0'; 
					break; 
				} 
			} 
1990/0504    
 
	/* 
1992/0610    
	 *  pack args into buffer 
1990/0504    
	 */ 
1992/0610    
	av = (char**)argbuf; 
	sp = argbuf + sizeof(argbuf); 
1990/0504    
	for(i = 0; i < _argc; i++){ 
1992/0610    
		if(i && *(_argv[i]) != '-') 
			diskless[0] = 0; 
		av[i] = pusharg(_argv[i]); 
1990/0504    
	} 
 
	/* 
1992/0610    
	 *  if no boot method is specified, look for 
	 *  a default in the diskless environment variable 
1990/0504    
	 */ 
1992/0610    
	if(diskless[0] > '1') 
		av[i++] = pusharg(diskless); 
	av[i] = 0; 
1990/1229    
} 
 
/* 
1990/1231    
 *  setup the IO2 lance, io buffers are in lance memory 
1990/1229    
 */ 
void 
1990/1231    
lanceIO2setup(Lance *lp) 
1990/1229    
{ 
1990/1231    
	ushort *sp; 
 
	/* 
	 *  reset lance and set parity on its memory 
	 */ 
	MODEREG->promenet &= ~1; 
	MODEREG->promenet |= 1; 
	for(sp = LANCERAM; sp < LANCEEND; sp += 1) 
		*sp = 0; 
 
	lp->sep = 1; 
	lp->lanceram = LANCERAM; 
	lp->lm = (Lancemem*)0; 
 
	/* 
	 *  Allocate space in lance memory for the io buffers. 
	 *  Start at 4k to avoid the initialization block and 
	 *  descriptor rings. 
	 */ 
	lp->lrp = (Etherpkt*)(4*1024); 
	lp->ltp = lp->lrp + lp->nrrb; 
	lp->rp = (Etherpkt*)(((ulong)LANCERAM) + (ulong)lp->lrp); 
	lp->tp = lp->rp + lp->nrrb; 
1990/1229    
} 
 
/* 
1990/1231    
 *  setup the IO3 lance, io buffers are in host memory mapped to 
 *  lance address space 
1990/1229    
 */ 
void 
1990/1231    
lanceIO3setup(Lance *lp) 
1990/1229    
{ 
1990/1231    
	ulong x, y; 
	int index; 
	ushort *sp; 
	int len; 
 
	/* 
	 *  reset lance and set parity on its memory 
	 */ 
	MODEREG->promenet |= 1; 
	MODEREG->promenet &= ~1; 
	for(sp = LANCE3RAM; sp < LANCE3END; sp += 2) 
		*sp = 0; 
 
	lp->sep = 4; 
	lp->lanceram = LANCE3RAM; 
	lp->lm = (Lancemem*)0x800000; 
 
	/* 
	 *  allocate some host memory for buffers and map it into lance 
	 *  space 
	 */ 
	len = (lp->nrrb + lp->ntrb)*sizeof(Etherpkt); 
1992/0622    
	lp->rp = (Etherpkt*)xspanalloc(len , BY2PG, 0); 
1990/1231    
	lp->tp = lp->rp + lp->nrrb; 
	x = (ulong)lp->rp; 
	lp->lrp = (Etherpkt*)(x & 0xFFF); 
	lp->ltp = lp->lrp + lp->nrrb; 
	index = LANCEINDEX; 
	for(y = x+len; x < y; x += 0x1000){ 
		*WRITEMAP = (index<<16) | (x>>12)&0xFFFF; 
		index++; 
	} 
1990/1229    
} 
 
/* 
1990/1231    
 *  set up the lance 
1990/1229    
 */ 
void 
1990/1231    
lancesetup(Lance *lp) 
1990/1229    
{ 
1990/1231    
	lp->rap = LANCERAP; 
	lp->rdp = LANCERDP; 
	lp->ea[0] = LANCEID[20]>>8; 
	lp->ea[1] = LANCEID[16]>>8; 
	lp->ea[2] = LANCEID[12]>>8; 
	lp->ea[3] = LANCEID[8]>>8; 
	lp->ea[4] = LANCEID[4]>>8; 
	lp->ea[5] = LANCEID[0]>>8; 
	lp->lognrrb = 7; 
	lp->logntrb = 7; 
	lp->nrrb = 1<<lp->lognrrb; 
	lp->ntrb = 1<<lp->logntrb; 
1991/0109    
	lp->busctl = BSWP; 
1990/1231    
	if(ioid >= IO3R1) 
		lanceIO3setup(lp); 
	else 
		lanceIO2setup(lp); 
1990/1229    
} 
 
void 
lanceparity(void) 
{ 
	print("lance DRAM parity error\n"); 
	MODEREG->promenet &= ~4; 
	MODEREG->promenet |= 4; 
1990/0227    
} 
1991/0607    
 
/* 
 *  for the sake of a single devcons.c 
 */ 
void 
buzz(int f, int d) 
{ 
1991/1214    
	USED(f); 
1992/0711    
	USED(d); 
1991/0607    
} 
1991/0705    
 
1991/0607    
int 
mouseputc(IOQ *q, int c) 
{ 
1991/1214    
	USED(q); 
1992/0711    
	USED(c); 
1991/0607    
	return 0; 
} 
 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)