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

1994/0619/carrera/main.c (diff list | history)

carrera/main.c on 1993/0903
1993/0903    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
#include	"init.h" 
 
/* 
 *  args passed by boot process 
 */ 
int _argc; char **_argv; char **_env; 
 
/* 
 *  arguments passed to initcode and /boot 
 */ 
char argbuf[128]; 
 
/* 
 *  environment passed to boot -- sysname, consname, diskid 
 */ 
char consname[NAMELEN]; 
char bootdisk[NAMELEN]; 
char screenldepth[NAMELEN]; 
 
/* 
 * software tlb simulation 
 */ 
Softtlb stlb[MAXMACH][STLBSIZE]; 
 
Conf	conf; 
FPsave	initfp; 
 
1994/0225    
int	int0mask = 0xff;	/* interrupts enabled for first 8259 */ 
int	int1mask = 0xff;	/* interrupts enabled for second 8259 */ 
 
1993/1210    
extern	uchar rdbgcode[]; 
extern	ulong	rdbglen; 
 
1993/0903    
void 
main(void) 
{ 
1993/1217    
	tlbinit(); 
	ioinit(1);		/* Very early to establish IO mappings */ 
1994/0322    
	rdbginit(); 
1993/0903    
	arginit(); 
	confinit(); 
	savefpregs(&initfp); 
	machinit(); 
	kmapinit(); 
	xinit(); 
1993/0905    
	iomapinit(); 
1993/0903    
	printinit(); 
1993/0905    
	serialinit(); 
1993/0903    
	vecinit(); 
1993/0918    
	screeninit(); 
1993/1015    
	iprint("\n\nBrazil\n"); 
1993/0903    
	pageinit(); 
	procinit0(); 
	initseg(); 
1993/0915    
	links(); 
1993/0903    
	chandevreset(); 
	swapinit(); 
	userinit(); 
	schedinit(); 
} 
 
1993/1217    
 
1993/0903    
/* 
 *  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. 
 * 
 *  also grab any environment variables that might be useful 
 */ 
struct 
{ 
	char	*name; 
	char	*val; 
1993/0904    
}bootenv[] = 
{ 
1993/0903    
	{"netaddr=",	sysname}, 
	{"console=",	consname}, 
	{"bootdisk=",	bootdisk}, 
	{"ldepth=",	screenldepth}, 
}; 
char *sp; 
 
char * 
pusharg(char *p) 
{ 
	int n; 
 
	n = strlen(p)+1; 
	sp -= n; 
	memmove(sp, p, n); 
	return sp; 
} 
 
void 
arginit(void) 
{ 
	int i, n; 
	char **av; 
 
	/* 
	 *  get boot env variables 
	 */ 
	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; 
				} 
			} 
 
	/* 
	 *  pack args into buffer 
	 */ 
	av = (char**)argbuf; 
	sp = argbuf + sizeof(argbuf); 
	for(i = 0; i < _argc; i++){ 
		if(strchr(_argv[i], '=')) 
			break; 
		av[i] = pusharg(_argv[i]); 
	} 
	av[i] = 0; 
} 
 
/* 
 *  initialize a processor's mach structure.  each processor does this 
 *  for itself. 
 */ 
void 
machinit(void) 
{ 
	int n; 
 
	/* Ensure CU1 is off */ 
	clrfpintr(); 
 
	/* scrub cache */ 
1994/0330    
	((void(*)(void))((ulong)cleancache|0xA0000000))(); 
1993/0903    
 
1993/1015    
	memset(m, 0, sizeof(Mach)); 
 
1993/0903    
	n = m->machno; 
	m->stb = &stlb[n][0]; 
1993/0904    
 
1993/0905    
	m->speed = 50; 
1993/0903    
	clockinit(); 
1993/0905    
 
	active.exiting = 0; 
	active.machs = 1; 
1993/0903    
} 
 
/* 
1993/0905    
 * Set up a console on serial port 2 
 */ 
void 
serialinit(void) 
{ 
	NS16552setup(Uart1, UartFREQ); 
	NS16552special(0, 9600, &kbdq, &printq, kbdcr2nl); 
1993/0907    
 
	kbdinit(); 
1993/0905    
} 
 
/* 
1993/0903    
 * Map IO address space in wired down TLB entry 1 
 */ 
void 
1993/0918    
ioinit(int mapeisa) 
1993/0903    
{ 
1994/0210    
	ulong devphys, isaphys, intphys, isamphys, promphys, ptec, ptes, v; 
1993/0903    
 
1993/0904    
	/* 
1993/0918    
	 * If you want to segattach the eisa space these 
	 * mappings must be turned off to prevent duplication 
	 * of the tlb entries 
	 */ 
	if(mapeisa) { 
		isaphys = IOPTE|PPN(Eisaphys)|PTEGLOBL; 
		isamphys = 0x04000000|IOPTE|PTEGLOBL; 
	} 
	else { 
		isaphys = PTEGLOBL; 
		isamphys = PTEGLOBL; 
	} 
 
	/* 
1993/0906    
	 * Map devices and the Eisa control space 
1993/0904    
	 */ 
1993/0908    
	devphys = IOPTE|PPN(Devicephys); 
1993/0906    
	puttlbx(1, Devicevirt, devphys, isaphys, PGSZ64K); 
 
1993/0904    
	/* 
1993/0907    
	 * Map Interrupt control & Eisa memory 
1993/0904    
	 */ 
1993/0908    
	intphys  = IOPTE|PPN(Intctlphys); 
1993/0907    
	puttlbx(2, Intctlvirt, intphys, isamphys, PGSZ1M); 
 
1993/1208    
	/* Enable all device interrupts */ 
1994/0516    
	IO(ushort, Intenareg) = 0xffff; 
1993/0908    
 
1993/1218    
	/* Map the rom back into Promvirt to allow NMI handling */ 
	promphys = IOPTE|PPN(Promphys); 
	puttlbx(3, Promvirt, promphys, PTEGLOBL, PGSZ1M); 
1994/0210    
 
	/* 8 MB video ram config */ 
	v = IO(ulong, 0xE0000004); 
	v &= ~(3<<8); 
	v |= (2<<8); 
	IO(ulong, 0xE0000004) = v; 
 
	/* Map the display hardware */ 
	ptec = PPN(VideoCTL)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED; 
	ptes = PPN(VideoMEM)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED; 
	puttlbx(4, Screenvirt, ptes, ptec, PGSZ4M); 
1994/0225    
 
	/* for PC weenies */ 
	/* 
	 *  Set up the first 8259 interrupt processor. 
	 *  Make 8259 interrupts start at CPU vector Int0vec. 
	 *  Set the 8259 as master with edge triggered 
	 *  input with fully nested interrupts. 
	 */ 
1994/0305    
	EISAOUTB(Int0ctl, 0x11);	/* ICW1 - edge triggered, master, 
					   ICW4 will be sent */ 
	EISAOUTB(Int0aux, Int0vec);	/* ICW2 - interrupt vector offset */ 
	EISAOUTB(Int0aux, 0x04);	/* ICW3 - have slave on level 2 */ 
	EISAOUTB(Int0aux, 0x01);	/* ICW4 - 8086 mode, not buffered */ 
1994/0225    
 
	/* 
	 *  Set up the second 8259 interrupt processor. 
	 *  Make 8259 interrupts start at CPU vector Int0vec. 
	 *  Set the 8259 as master with edge triggered 
	 *  input with fully nested interrupts. 
	 */ 
1994/0305    
	EISAOUTB(Int1ctl, 0x11);	/* ICW1 - edge triggered, master, 
					   ICW4 will be sent */ 
	EISAOUTB(Int1aux, Int1vec);	/* ICW2 - interrupt vector offset */ 
	EISAOUTB(Int1aux, 0x02);	/* ICW3 - I am a slave on level 2 */ 
	EISAOUTB(Int1aux, 0x01);	/* ICW4 - 8086 mode, not buffered */ 
1994/0225    
 
	/* 
	 *  pass #2 8259 interrupts to #1 
	 */ 
 
	/* enable all PC interrupts except the clock */ 
1994/0307    
	int0mask = 0; 
1994/0225    
	int0mask |= 1<<(Clockvec&7); 
	EISAOUTB(Int0aux, int0mask); 
1994/0306    
 
1994/0225    
	int1mask = 0; 
	EISAOUTB(Int1aux, int1mask); 
1994/0306    
 
	IO(ulong, R4030ier) = 0xf;	/* enable eisa interrupts */ 
1993/1208    
} 
 
1993/0906    
/* 
 * Pull the ethernet address out of NVRAM 
 */ 
1993/0905    
void 
enetaddr(uchar *ea) 
{ 
1993/0906    
	int i; 
	uchar tbuf[8]; 
1993/0905    
 
1993/0906    
	for(i = 0; i < 8; i++) 
		tbuf[i] = ((uchar*)(NvramRO+Enetoffset))[i]; 
 
	print("ether:"); 
	for(i = 0; i < 6; i++) { 
		ea[i] = tbuf[7-i]; 
		print("%2.2ux", ea[i]); 
	} 
	print("\n"); 
1993/0905    
} 
 
1993/0903    
/* 
1993/0905    
 * All DMA and ether IO buffers must reside in the first 16M bytes of 
 * memory to be covered by the translation registers 
 */ 
void 
iomapinit(void) 
{ 
	int i; 
	Tte *t; 
 
	t = xspanalloc(Ntranslation*sizeof(Tte), BY2PG, 0); 
 
	for(i = 0; i < Ntranslation; i++) 
		t[i].lo = i<<PGSHIFT; 
 
	/* Set the translation table */ 
	IO(ulong, Ttbr) = PADDR(t); 
1994/0115    
	IO(ulong, Tlrb) = Ntranslation*sizeof(Tte); 
1993/0905    
 
	/* Invalidate the old entries */ 
	IO(ulong, Tir) = 0; 
} 
 
/* 
1993/0903    
 *  setup MIPS trap vectors 
 */ 
void 
vecinit(void) 
{ 
1994/0619    
	memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80); 
	memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80); 
1993/0903    
	memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80); 
	memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80); 
1993/0904    
 
	icflush((ulong*)UTLBMISS, 8*1024); 
1993/0903    
} 
 
void 
init0(void) 
{ 
	char buf[2*NAMELEN]; 
1994/0207    
 
1993/0903    
	spllo(); 
 
	/* 
	 * These are o.k. because rootinit is null. 
	 * Then early kproc's will have a root and dot. 
	 */ 
	up->slash = namec("#/", Atodir, 0, 0); 
	up->dot = clone(up->slash, 0); 
 
	chandevinit(); 
 
	if(!waserror()){ 
		ksetenv("cputype", "mips"); 
1993/1005    
		sprint(buf, "carrera %s R4400PC", conffile); 
1993/0903    
		ksetenv("terminal", buf); 
		ksetenv("sysname", sysname); 
		poperror(); 
	} 
 
	kproc("alarm", alarmkproc, 0); 
	touser((uchar*)(USTKTOP-sizeof(argbuf))); 
} 
 
void 
userinit(void) 
{ 
	Proc *p; 
	KMap *k; 
	Page *pg; 
	char **av; 
	Segment *s; 
 
	p = newproc(); 
	p->pgrp = newpgrp(); 
	p->egrp = smalloc(sizeof(Egrp)); 
	p->egrp->ref = 1; 
	p->fgrp = smalloc(sizeof(Fgrp)); 
	p->fgrp->ref = 1; 
	p->procmode = 0640; 
 
	strcpy(p->text, "*init*"); 
	strcpy(p->user, eve); 
 
	p->fpstate = FPinit; 
	p->fpsave.fpstatus = initfp.fpstatus; 
 
	/* 
	 * Kernel Stack 
	 */ 
	p->sched.pc = (ulong)init0; 
	p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD; 
	/* 
	 * User Stack, pass input arguments to boot process 
	 */ 
	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); 
	p->seg[SSEG] = s; 
	pg = newpage(1, 0, USTKTOP-BY2PG); 
	segpage(s, pg); 
	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); 
 
	/* Text */ 
	s = newseg(SG_TEXT, UTZERO, 1); 
	s->flushme++; 
	p->seg[TSEG] = s; 
	pg = newpage(1, 0, UTZERO); 
	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); 
	segpage(s, pg); 
	k = kmap(s->map[0]->pages[0]); 
	memmove((ulong*)VA(k), initcode, sizeof initcode); 
	kunmap(k); 
 
	ready(p); 
} 
 
void 
exit(long type) 
{ 
1993/1221    
	uchar *vec; 
 
1993/0905    
	USED(type); 
1993/0903    
 
	spllo(); 
1994/0528    
	print("cpu%d exiting\n", m->machno); 
1993/0904    
	while(consactive()) 
1993/0903    
		delay(10); 
1993/1221    
 
1993/0903    
	splhi(); 
1993/1221    
	/* Turn off the NMI hander for the debugger */ 
	vec = (uchar*)0xA0000420; 
	vec[0] = 0; 
1994/0528    
 
	firmware(type); 
1993/0903    
} 
 
void 
confinit(void) 
{ 
	ulong ktop, top; 
 
	ktop = PGROUND((ulong)end); 
	ktop = PADDR(ktop); 
	top = (16*1024*1024)/BY2PG; 
 
	conf.base0 = 0; 
	conf.npage0 = top; 
	conf.npage = conf.npage0; 
	conf.npage0 -= ktop/BY2PG; 
	conf.base0 += ktop; 
	conf.npage1 = 0; 
	conf.base1 = 0; 
 
1993/1015    
	conf.upages = (conf.npage*70)/100; 
1994/0322    
	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; 
1993/0903    
 
	conf.nmach = 1; 
 
	/* set up other configuration parameters */ 
	conf.nproc = 100; 
1993/0904    
	conf.nswap = conf.npage*3; 
1993/0903    
	conf.nimage = 200; 
 
1993/0918    
	conf.monitor = 1; 
1993/0906    
 
1993/0905    
	conf.copymode = 0;		/* copy on write */ 
1993/0903    
} 
 
1993/1217    
void 
procsave(Proc *p) 
{ 
	USED(p); 
1993/0903    
 
1993/1217    
	/* keep track of tlbfaults */ 
	m->otlbfault = m->tlbfault; 
} 
1993/0903    
 
void 
buzz(int f, int d) 
{ 
	USED(f); 
	USED(d); 
1993/1210    
} 
 
1993/1217    
/* 
	register offsets of ARCS prom jmpbuf 
		JB_PC		0 
		JB_SP		1 
		JB_FP		2 
		JB_S0		3 
		JB_S1		4 
		JB_S2		5 
		JB_S3		6 
		JB_S4		7 
		JB_S5		8 
		JB_S6		9 
		JB_S7		10 
*/ 
 
struct  
1993/1210    
{ 
1993/1217    
	ulong	pc; 
	ulong	sp; 
	ulong	fp; 
	ulong	s[7]; 
} Mipsjmpbuf; 
1993/1214    
 
void 
1993/1217    
rdbginit(void) 
1993/1214    
{ 
1993/1217    
	uchar *vec; 
	ulong jba; 
1994/0413    
return;/**/ 
1993/1217    
	/* Only interested in the PC */ 
1994/0415    
	Mipsjmpbuf.pc = 0xA001C020; 
1993/1217    
 
	/* Link an NMI handler to the debugger 
	 * - addresses from the ARCS rom source 
	 */ 
	vec = (uchar*)0xA0000420; 
	jba = (ulong)UNCACHED(void, &Mipsjmpbuf); 
 
	vec[0] = 'N'; 
	vec[1] = 'm'; 
	vec[2] = 'i'; 
	vec[3] = 's'; 
	vec[4] = jba>>24; 
	vec[5] = jba>>16; 
	vec[6] = jba>>8; 
	vec[7] = jba; 
 
	/* Install the debugger code in a known place */ 
1994/0415    
	memmove((void*)0xA001C000, rdbgcode, rdbglen); 
1993/1214    
} 


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