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

1990/0825/power/main.c (diff list | history)

power/main.c on 1990/0227
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
#include	"ureg.h" 
#include	"init.h" 
 
1990/0424    
/* 
 *  args passed by boot process 
 */ 
int _argc; char **_argv; char **_env; 
 
1990/0504    
/* 
 *  arguments passed to initcode 
 */ 
1990/0427    
char argbuf[512]; 
int argsize; 
1990/0424    
 
1990/0504    
/* 
 *  environment passed to any kernel started by this kernel 
 */ 
char envbuf[64]; 
char *env[2]; 
 
/* 
 *  configuration file read by boot program 
 */ 
char confbuf[4*1024]; 
 
/* 
 *  system name 
 */ 
char sysname[64]; 
 
1990/0227    
void 
main(void) 
{ 
1990/0424    
	int i; 
 
1990/0801    
	machinit(); 
1990/0227    
	active.exiting = 0; 
	active.machs = 1; 
	confinit(); 
1990/0504    
	arginit(); 
1990/0227    
	lockinit(); 
	printinit(); 
	tlbinit(); 
	vecinit(); 
	procinit0(); 
	pgrpinit(); 
	chaninit(); 
	clockinit(); 
	alarminit(); 
	io2init(); 
	chandevreset(); 
	streaminit(); 
1990/0718    
	sysloginit(); 
1990/0227    
	pageinit(); 
	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; 
	m->mmask = 1<<m->machno; 
} 
 
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; 
	q = (ulong*)vector80; 
	for(size=0; size<4; size++) 
		*p++ = *q++; 
} 
 
/* 
 *  We have to program both the IO2 board to generate interrupts 
 *  and the SBCC on CPU 0 to accept them. 
 */ 
void 
io2init(void) 
{ 
	long i; 
 
	/* 
	 *  reset VME bus (MODEREG is on the IO2) 
	 */ 
	MODEREG->resetforce = (1<<1); 
	for(i=0; i<1000000; i++) 
		; 
	MODEREG->resetforce = 0; 
	MODEREG->masterslave = (SLAVE<<4) | MASTER; 
 
	/* 
	 *  all VME interrupts to the error routine 
	 */ 
	for(i=0; i<256; i++) 
		setvmevec(i, novme); 
 
	/* 
	 *  tell IO2 to sent all interrupts to CPU 0's SBCC 
	 */ 
	for(i=0; i<8; i++) 
		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. 
	 */ 
	SBCCREG->fintenable |= 0xff;	  /* allow all interrupts on the IO2 */ 
	SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */ 
 
	/* 
	 *  enable all interrupts on the IO2 
	 */ 
	*IO2SETMASK = 0xff; 
} 
 
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) 
{ 
1990/0424    
	int i; 
1990/0427    
	ulong *sp; 
1990/0424    
 
1990/0227    
	m->proc = u->p; 
	u->p->state = Running; 
	u->p->mach = m; 
	spllo(); 
1990/0427    
 
1990/0227    
	chandevinit(); 
1990/0424    
 
1990/0227    
	u->slash = (*devtab[0].attach)(0); 
	u->dot = clone(u->slash, 0); 
 
1990/0427    
	sp = (ulong*)(USTKTOP - argsize); 
 
	touser(sp); 
1990/0227    
} 
 
FPsave	initfp; 
 
void 
userinit(void) 
{ 
	Proc *p; 
	Seg *s; 
	User *up; 
1990/0617    
	KMap *k; 
1990/0427    
	int i; 
	char **av; 
1990/0227    
 
	p = newproc(); 
	p->pgrp = newpgrp(); 
	strcpy(p->text, "*init*"); 
	strcpy(p->pgrp->user, "bootes"); 
	savefpregs(&initfp); 
	p->fpstate = FPinit; 
 
	/* 
	 * Kernel Stack 
	 */ 
	p->sched.pc = (ulong)init0; 
	p->sched.sp = USERADDR+BY2PG-20; 
	p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF)); 
 
	/* 
	 * User 
	 */ 
1990/0617    
	k = kmap(p->upage); 
	up = (User*)VA(k); 
1990/0227    
	up->p = p; 
1990/0617    
	kunmap(k); 
1990/0227    
 
	/* 
1990/0427    
	 * User Stack, pass input arguments to boot process 
1990/0227    
	 */ 
	s = &p->seg[SSEG]; 
	s->proc = p; 
	s->o = neworig(USTKTOP-BY2PG, 1, OWRPERM, 0); 
1990/0427    
	s->o->pte[0].page = newpage(0, 0, USTKTOP-BY2PG); 
	memcpy((ulong*)(s->o->pte[0].page->pa|KZERO|(BY2PG-argsize)),  
		argbuf + sizeof(argbuf) - argsize, argsize); 
	av = (char **)(s->o->pte[0].page->pa|KZERO|(BY2PG-argsize)); 
	for(i = 0; i < _argc; i++) 
		av[i] += (char *)USTKTOP - (argbuf + sizeof(argbuf)); 
1990/0227    
	s->minva = USTKTOP-BY2PG; 
	s->maxva = USTKTOP; 
 
	/* 
	 * Text 
	 */ 
	s = &p->seg[TSEG]; 
	s->proc = p; 
1990/0802    
	/* 
	 * On the mips, init text must be OCACHED to avoid reusing page 
	 * and getting in trouble with the hardware instruction cache. 
	 */ 
	s->o = neworig(UTZERO, 1, OCACHED, 0); 
1990/0227    
	s->o->pte[0].page = newpage(0, 0, UTZERO); 
1990/0802    
	s->o->npage = 1; 
1990/0617    
	k = kmap(s->o->pte[0].page); 
	memcpy((ulong*)VA(k), initcode, sizeof initcode); 
	kunmap(k); 
1990/0227    
	s->minva = 0x1000; 
	s->maxva = 0x2000; 
 
	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; 
	long i; 
 
	p = (Beef*) 0xb0000500 + n; 
	p->launch = newstart; 
	p->sum -= (long)newstart; 
	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 
exit(void) 
{ 
	int i; 
 
	u = 0; 
	lock(&active); 
	active.machs &= ~(1<<m->machno); 
	active.exiting = 1; 
	unlock(&active); 
	spllo(); 
	print("cpu %d exiting\n", m->machno); 
	while(active.machs || consactive()) 
		for(i=0; i<1000; i++) 
			; 
	splhi(); 
	for(i=0; i<2000000; i++) 
		; 
	duartreset(); 
	firmware(); 
} 
 
/* 
 * Insert new into list after where 
 */ 
void 
insert(List **head, List *where, List *new) 
{ 
	if(where == 0){ 
		new->next = *head; 
		*head = new; 
	}else{ 
		new->next = where->next; 
		where->next = new; 
	} 
		 
} 
 
/* 
 * Insert new into list at end 
 */ 
void 
append(List **head, List *new) 
{ 
	List *where; 
 
	where = *head; 
	if(where == 0) 
		*head = new; 
	else{ 
		while(where->next) 
			where = where->next; 
		where->next = new; 
	} 
	new->next = 0; 
} 
 
/* 
 * Delete old from list 
 */ 
void 
delete0(List **head, List *old) 
{ 
	List *l; 
 
	l = *head; 
	if(l == old){ 
		*head = old->next; 
		return; 
	} 
	while(l->next != old) 
		l = l->next; 
	l->next = old->next; 
} 
 
/* 
 * Delete old from list.  where->next is known to be old. 
 */ 
void 
delete(List **head, List *where, List *old) 
{ 
	if(where == 0){ 
		*head = old->next; 
		return; 
	} 
	where->next = old->next; 
} 
 
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; 
	ulong x; 
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); 
	} 
} 
 
/* 
 *  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) 
{ 
	long x, i, j, *l; 
 
	/* 
	 *  copy configuration down from high memory 
	 */ 
	strcpy(confbuf, (char *)(0x80000000 + 4*1024*1024 - 4*1024)); 
 
	/* 
	 *  size memory 
	 */ 
1990/0227    
	x = 0x12345678; 
1990/0322    
	for(i=4; i<128; i+=4){ 
1990/0227    
		l = (long*)(KSEG1|(i*1024L*1024L)); 
		*l = x; 
		wbflush(); 
		*(ulong*)KSEG1 = *(ulong*)KSEG1;	/* clear latches */ 
		if(*l != x) 
			break; 
		x += 0x3141526; 
	} 
1990/0614    
	conf.npage0 = i*1024/4; 
	conf.npage = conf.npage0; 
1990/0504    
 
	/* 
	 *  set minimal default values 
	 */ 
	conf.nmach = 1; 
	conf.nmod = 2000; 
	conf.nalarm = 1000; 
	conf.norig = 9; 
	conf.nchan = 64; 
	conf.nenv = 4; 
	conf.nenvchar = 1000; 
	conf.npgenv = 400; 
	conf.nmtab = 4; 
	conf.nmount = 4; 
	conf.nmntdev = 4; 
	conf.nmntbuf = 4; 
	conf.nmnthdr = 4; 
	conf.nstream = 4; 
	conf.nsrv = 0; 
	conf.nproc = 4; 
	conf.npgrp = 4; 
1990/0424    
	conf.npte = 4 * conf.npage; 
1990/0227    
	conf.nqueue = 5 * conf.nstream; 
	conf.nblock = 16 * conf.nstream; 
1990/0430    
 
1990/0504    
	confread(); 
 
	if(conf.nmach > MAXMACH) 
		panic("confinit"); 
 
} 
 
/* 
 *  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. 
 */ 
#define SYSENV "netaddr=" 
void 
arginit(void) 
{ 
	int i, n; 
	int nbytes; 
	int ssize; 
	char *p; 
	char **argv; 
	char *charp; 
 
1990/0430    
	/* 
1990/0504    
	 *  get the system name from the environment 
1990/0430    
	 */ 
1990/0504    
	if(*sysname == 0){ 
		for(argv = _env; *argv; argv++){ 
			if(strncmp(*argv, SYSENV, sizeof(SYSENV)-1)==0){ 
				strcpy(sysname, (*argv) + sizeof(SYSENV)-1); 
				break; 
			} 
		} 
	} 
	strcpy(envbuf, SYSENV); 
	strcat(envbuf, sysname); 
	env[0] = envbuf; 
	env[1] = 0; 
 
	/* 
	 *  trim arguments to make them fit in the buffer (argv[0] is sysname) 
	 */ 
	nbytes = 0; 
	_argv[0] = sysname; 
	for(i = 0; i < _argc; i++){ 
		n = strlen(_argv[i]) + 1; 
		ssize = BY2WD*(i+2) + ((nbytes+n+(BY2WD-1)) & ~(BY2WD-1)); 
		if(ssize > sizeof(argbuf)) 
			break; 
		nbytes += n; 
	} 
	_argc = i; 
	ssize = BY2WD*(i+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); 
 
	/* 
	 *  copy arguments into the buffer 
	 */ 
	argv = (char**)(argbuf + sizeof(argbuf) - ssize); 
	charp = (char*)(argbuf + sizeof(argbuf) - nbytes); 
	for(i=0; i<_argc; i++){ 
		argv[i] = charp; 
		n = strlen(_argv[i]) + 1; 
		memcpy(charp, _argv[i], n); 
		charp += n; 
	} 
	_argv = argv; 
	argsize = ssize; 
1990/0227    
} 


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