511 lines · 8.6 KB · C
RawDownload
#include	"all.h"#include	"mem.h"#include	"io.h"#include	"ureg.h" /* * Where configuration info is left for the loaded programme. * This will turn into a structure as more is done by the boot loader * (e.g. why parse the .ini file twice?). * There are 1024 bytes available at CONFADDR. */#define BOOTLINE	((char*)CONFADDR)#define BOOTLINELEN	64#define BOOTARGS	((char*)(CONFADDR+BOOTLINELEN))#define	BOOTARGSLEN	(1024-BOOTLINELEN)#define	MAXCONF		32 char bootdisk[NAMELEN];char *confname[MAXCONF];char *confval[MAXCONF];int nconf; intgetcfields(char* lp, char** fields, int n, char* sep){	int i; 	for(i = 0; lp && *lp && i < n; i++){		while(*lp && strchr(sep, *lp) != 0)			*lp++ = 0;		if(*lp == 0)			break;		fields[i] = lp;		while(*lp && strchr(sep, *lp) == 0){			if(*lp == '\\' && *(lp+1) == '\n')				*lp++ = ' ';			lp++;		}	} 	return i;} static voidoptions(void){	long i, n;	char *cp, *line[MAXCONF], *p, *q; 	/*	 *  parse configuration args from dos file plan9.ini	 */	cp = BOOTARGS;	/* where b.com leaves its config */	cp[BOOTARGSLEN-1] = 0; 	/*	 * Strip out '\r', change '\t' -> ' '.	 */	p = cp;	for(q = cp; *q; q++){		if(*q == '\r')			continue;		if(*q == '\t')			*q = ' ';		*p++ = *q;	}	*p = 0; 	n = getcfields(cp, line, MAXCONF, "\n");	for(i = 0; i < n; i++){		if(*line[i] == '#')			continue;		cp = strchr(line[i], '=');		if(cp == 0)			continue;		*cp++ = 0;		if(cp - line[i] >= NAMELEN+1)			*(line[i]+NAMELEN-1) = 0;		confname[nconf] = line[i];		confval[nconf] = cp;		nconf++;	}}  /* * Vecinit is the first hook we have into configuring the machine, * so we do it all here. A pox on special fileserver code. * We do more in meminit below. */voidvecinit(void){	options();} char*getconf(char *name){	int i; 	for(i = 0; i < nconf; i++)		if(cistrcmp(confname[i], name) == 0)			return confval[i];	return 0;} /* * old memory scan.  if no e820 information is available, * this kernel will see MAXMEG megabytes of RAM at most. * maxmeg is limited due the the fact the page table might be too large * for our temporary mapping to hold and depends on the size of  * our kernel. */#ifndef MAXMEG#define MAXMEG 2015#endif char mmap[MAXMEG+2];Mconf mconf; static voidmconfscan(void){	ulong x, i, j, ktop;	Mbank *b; 	/*	 *  size memory above 4 meg. Kernel sits at 1 meg.  We	 *  only recognize MB size chunks.	 */	x = 0x12345678;	for(i = 4; i <= MAXMEG; i++){		/*		 *  write the first & last word in a megabyte of memory		 */		*mapaddr(i*MB) = x;		*mapaddr((i+1)*MB-BY2WD) = x; 		/*		 *  write the first and last word in all previous megs to		 *  handle address wrap around		 */		for(j = 4; j < i; j++){			*mapaddr(j*MB) = ~x;			*mapaddr((j+1)*MB-BY2WD) = ~x;		} 		/*		 *  check for correct value		 */		if(*mapaddr(i*MB) == x && *mapaddr((i+1)*MB-BY2WD) == x)			mmap[i] = 'x';		x += 0x3141526;	} 	b = mconf.bank;	ktop = PGROUND((ulong)end);	ktop = PADDR(ktop);	b->base = ktop;	/* careful with that ax, eugene */	for(i = 4; mmap[i] == 'x'; i++)		;	b->limit = i*MB;	mconf.topofmem = b->limit;	b++; 	/*	 * Look for any other chunks of memory.	 */	for(; i <= MAXMEG; i++){		if(mmap[i] == 'x'){			b->base = i*MB;			for(j = i+1; mmap[j] == 'x'; j++)				;			b->limit = j*MB;			mconf.topofmem = j*MB;			b++; 			if(b - mconf.bank == MAXBANK)				break;		}	} 	mconf.nbank = b - mconf.bank;} typedef struct {	uvlong base;	uvlong len;	ulong type;}Emap; static char *etypes[] ={	"type=0",	"memory",	"reserved",	"acpi reclaim",	"acpi nvs",}; #define	smap		0x534d4150#define	e820tab		0x2d0#define	e820sz		20#define	e820end		(16*e820sz+e820tab) /* debugging crap */ulong n820;ulong n820m;static Emap emap[16]; intmconf820(void){	ulong i;	Emap *e, *t;	Mbank *b;	uchar *a;	vlong sz; 	a = (uchar*)mapaddr(0);	i = *(ulong*)(a+e820end);	if(i == 0 || i > 16)		return -1;	e = (Emap*)(a+e820tab);	t = e+i;	b = mconf.bank;	mconf.topofmem = MB;		// this is used to calculate pgtable sz; allow pci space.	for(; e<=t; e++){		emap[n820].base = e->base;		emap[n820].len = e->len;		emap[n820++].type = e->type; 		if(e->type != 1)			continue;		if(e->base >= 1ULL<<32 || e->base == 0)			continue;		sz = e->len;		b->base = e->base;		b->limit = e->base+sz;		mconf.topofmem += sz;		if(++b-mconf.bank == MAXBANK)			break;	}	mconf.topofmem &= ~(4*MB-1); 	n820m = b-mconf.bank;	if(b-mconf.bank < 1)		return 0;	mconf.nbank = b-mconf.bank;	/* careful with that axe, eugene */	mconf.bank[0].base += PADDR(PGROUND((ulong)end)); 	return mconf.nbank;} /* debugging aide -- please remove */voidcmd_e820(int, char **){	ulong n;	Emap *e, *end;	vlong sz, ex, lim; 	print("found %uld e820 entries %uld banks\n", n820, n820m); 	e = emap;	end = e+n820;		n = 0;	sz = 0;	ex = 0;	for(; e<end; e++){		print("e820: %.8llux %.8llux ", e->base, e->base+e->len);		if(e->type < nelem(etypes))			print("%s\n", etypes[e->type]);		else			print("type=%lud\n", e->type); 		if(e->type != 1 || e->base == 0)			continue;		if(e->base >= 1ULL<<32){			ex += e->len;			continue;		}		lim = e->base+e->len;		sz += e->len;		if(++n == MAXBANK)			continue; 		print("\t" "bank %ullx %ullx\n", e->base, lim);	} 	print("found %ld e820 memory banks %ulldMB+%ulldMB\n", n, sz/MB, ex/MB);	print("	topofmem = %p\n", mconf.topofmem);	print("	cpuiddx %p; cycles %p\n", MACHP(0)->cpuiddx, cycles);	if((MACHP(0)->cpuiddx & 0x08) && (getcr4() & 0x10))		print("	pse: yes\n");} ulongmeminit(void){	ulong i, sz; 	conf.nmach = 1;	if(mconf820() <= 0)		mconfscan();	mmuinit();	trapinit(); 	sz = 0;	for(i = 0; i < mconf.nbank; i++)		sz += mconf.bank[i].limit-mconf.bank[i].base;	return sz;} voiduserinit(void (*f)(void), void *arg, char *text){	User *p; 	p = newproc(); 	/*	 * Kernel Stack.	 * The -4 is because the path sched()->gotolabel()->init0()->f()	 * uses a stack location without creating any local space.	 */	p->sched.pc = (ulong)init0;	p->sched.sp = (ulong)p->stack + sizeof(p->stack) - 4;	p->start = f;	p->text = text;	p->arg = arg; 	dofilter(&p->time);	ready(p);} static int useuart;static void (*intrputs)(char*, int); static intpcgetc(void){	int c; 	if(c = kbdgetc())		return c;	if(c = cecgetc())		return c;	if(useuart)		return uartgetc();	return 0;} static voidpcputc(int c){	if(predawn)		cgaputc(c);	if(useuart)		uartputc(c);} static voidpcputs(char* s, int n){	if(!predawn){		cgaputs(s, n);		cecputs(s, n);	}	if(intrputs)		(*intrputs)(s, n);} voidconsinit(void (*puts)(char*, int)){	char *p;	int baud, port; 	kbdinit(); 	consgetc = pcgetc;	consputc = pcputc;	consputs = pcputs;	intrputs = puts; 	if((p = getconf("console")) == 0 || cistrcmp(p, "cga") == 0)		return; 	port = strtoul(p, &p, 0);	if(port < 0 || port > 1)		return;	while(*p == ' ' || *p == '\t')		p++;	if(*p != 'b' || (baud = strtoul(p+1, 0, 0)) == 0)		baud = 9600; 	uartspecial(port, kbdchar, conschar, baud);	useuart = 1;} voidconsreset(void){} voidfirmware(void){	char *p; 	/*	 * Always called splhi().	 */	if((p = getconf("reset")) && cistrcmp(p, "manual") == 0){		predawn = 1;		print("\nHit Reset\n");		for(;;);	}	pcireset();	i8042reset();} intisaconfig(char *class, int ctlrno, ISAConf *isa){	char cc[NAMELEN], *p, *q, *r;	int n; 	sprint(cc, "%s%d", class, ctlrno);	for(n = 0; n < nconf; n++){		if(cistrncmp(confname[n], cc, NAMELEN))			continue;		isa->nopt = 0;		p = confval[n];		while(*p){			while(*p == ' ' || *p == '\t')				p++;			if(*p == '\0')				break;			if(cistrncmp(p, "type=", 5) == 0){				p += 5;				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){					if(*p == '\0' || *p == ' ' || *p == '\t')						break;					*q = *p++;				}				*q = '\0';			}			else if(cistrncmp(p, "port=", 5) == 0)				isa->port = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "irq=", 4) == 0)				isa->irq = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "dma=", 4) == 0)				isa->dma = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "mem=", 4) == 0)				isa->mem = strtoul(p+4, &p, 0);			else if(cistrncmp(p, "size=", 5) == 0)				isa->size = strtoul(p+5, &p, 0);			else if(cistrncmp(p, "freq=", 5) == 0)				isa->freq = strtoul(p+5, &p, 0);			else if(isa->nopt < NISAOPT){				r = isa->opt[isa->nopt];				while(*p && *p != ' ' && *p != '\t'){					*r++ = *p++;					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)						break;				}				*r = '\0';				isa->nopt++;			}			while(*p && *p != ' ' && *p != '\t')				p++;		}		return 1;	}	return 0;} voidlockinit(void){} voidlaunchinit(void){} voidlights(int, int){} /* in assembly languageFloat

Lines 1–500 of 511.