xref: /inferno-os/os/js/main.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"io.h"
7 #include	"version.h"
8 
9 Mach *m = &mach0;
10 Proc *up;
11 int cflag;
12 
13 ulong cachetable[1024];
14 
15 Sysint	*sysintr;
16 struct {
17 	uchar	format;
18 	uchar	type;
19 	uchar	ea[6];
20 	uchar	pad[32-8];
21 } idprom;
22 
23 int	cpuserver;
24 ulong	bank[8];
25 uchar	mempres[64];
26 char	fbstr[32];
27 ulong	fbslot;
28 int	usecg6;
29 Label	catch;
30 uchar	*sp;
31 
32 int cold=1;
33 
34 typedef struct Sysparam Sysparam;
35 struct Sysparam
36 {
37 	int	id;		/* Model type from id prom */
38 	char	*name;		/* System name */
39 	char	ss2;		/* Is Sparcstation 2? */
40 	int	vacsize;	/* Cache size */
41 	int	vacline;	/* Cache line size */
42 	int	ncontext;	/* Number of MMU contexts */
43 	char	cachebug;	/* Machine needs cache bug work around */
44 	int	nbank;		/* Number of banks of memory */
45 	int	banksize;	/* Maximum Mbytes per bank */
46 	int	pcnt;		/* percent of mem for kernel? */
47 }
48 sysparam[] =
49 {
50 	{ 0xFF, "unknown Sun4M",0, 0, 0,  64, 0, 4, 32 ,0},
51 	{ 0x80, "JavaStation uSparcII",0, 0, 0,  256, 0, 4, 32 ,2},
52 	{ 0 }
53 };
54 Sysparam *sparam;
55 
56 void
57 doc(char *m)
58 {
59 	print("%s\n", m);
60 }
61 
62 static void poolsizeinit(void);
63 
64 void
65 main(void)
66 {
67 
68 
69 	machinit();
70 	trapinit();
71 	quotefmtinstall();
72 	confinit();
73 	xinit();
74 	mmuinit();
75 	intrinit();
76 	clockinit();
77 	printinit();
78 	screeninit();
79 	ioinit();
80 	doc("ioinit...");
81 	ns16552install();
82 	poolsizeinit();
83 	doc("ns16552install...");
84 	kbdinit();
85 	doc("kbdinit...");
86 	cacheinit();
87 	doc("cacheinit...");
88 	procinit();
89 	doc("procinit...");
90 	putphys(MID, 0x1F<<16);	/* enable arbitration */
91 	links();
92 	doc("links");
93 	chandevreset();
94 	doc("chandevreset...");
95 
96 	print("\nInferno Operating System\n");
97 	print("%s-%s \n\n",VERSION, conffile);
98 	print("JIT Compilation Mode = %d\n",cflag);
99 
100 	userinit();
101 	doc("userinit...");
102 
103 	 /* clear pending processor interrupts */
104 	putphys(PROCINTCLR, (~0<<17)|(1<<15));
105 	print("berore schedinit\n");
106 	schedinit();
107 }
108 
109 extern int main_pool_pcnt;
110 extern int heap_pool_pcnt;
111 extern int image_pool_pcnt;
112 
113 static void
114 poolsizeinit(void)
115 {
116 	ulong nb = conf.npage*BY2PG;
117 
118 	print("Total memory available: %ld K\n",nb/1024);
119 	poolsize(mainmem, (nb*main_pool_pcnt)/100, 0);
120 	poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0);
121 	poolsize(imagmem, (nb*image_pool_pcnt)/100, 1);
122 }
123 
124 void
125 intrinit(void)
126 {
127 	KMap *k;
128 
129 	 /* clear fault status */
130 	getphys(AFSR);
131 
132 	k = kmappa(SYSINTR, PTEIO|PTENOCACHE);
133 	sysintr = (Sysint*)VA(k);
134 
135 	 /* mask all interrupts */
136 	sysintr->maskset = ~0;
137 
138    	 /* allow these */
139 	sysintr->maskclr=MaskAllIntr|MEIntr|MSIIntr|EMCIntr|EtherIntr|KbdIntr;
140 
141 	 /* clear pending processor interrupts */
142 	putphys(PROCINTCLR, (~0<<17)|(1<<15));
143 
144 }
145 
146 void
147 systemreset(void)
148 {
149 	microdelay(200);
150 	putphys(SYSCTL, getphys(SYSCTL)|1);	/* power on reset */
151 }
152 
153 void
154 machinit(void)
155 {
156 	memset(m, 0, sizeof(Mach));
157 }
158 
159 void
160 ioinit(void)
161 {
162 	KMap *k;
163 	uchar *sindex;	/* superio index */
164 	uchar *sdata;	/* superio data */
165 	uchar *mkctl;	/* superio mouse/kbd ctl register */
166 	uchar *mkdata;	/* superio mouse/kbd data register */
167 
168 
169 	 /* enable the uart's on the superio chip */
170 	k = kmappa(SUPERIO_PHYS_PAGE, PTEIO|PTENOCACHE);
171 	sindex = (uchar*)(VA(k)+SUPERIO_INDEX_OFFSET);
172 	sdata = (uchar*)(VA(k)+SUPERIO_DATA_OFFSET);
173 	mkdata = (uchar*)(VA(k)+SUPERIO_MOUSE_KBD_DATA_PORT);
174 	mkctl = (uchar*)(VA(k)+SUPERIO_MOUSE_KBD_CTL_PORT);
175 
176 	superioinit(VA(k),sindex,sdata,mkctl,mkdata);
177 	doc("superioinit...");
178 }
179 
180 void
181 init0(void)
182 {
183 	Osenv *o;
184 
185 	up->nerrlab = 0;
186 
187 	print("before spllo");
188 
189 	spllo();
190 
191 	print("Sun Sparc %s\n", sparam->name);
192 	print("bank 0: %ldM  1: %ldM\n", bank[0], bank[1]);
193 	print("frame buffer id %lux slot %ld %s\n",conf.monitor,fbslot,fbstr);
194 
195 
196 	if(waserror())
197 		panic("init0");
198 
199 	/*
200 	 * These are o.k. because rootinit is null.
201 	 * Then early kproc's will have a root and dot.
202 	 */
203 	o = up->env;
204 	o->pgrp->slash = namec("#/", Atodir, 0, 0);
205 	cnameclose(o->pgrp->slash->name);
206 	o->pgrp->slash->name = newcname("/");
207 	o->pgrp->dot = cclone(o->pgrp->slash);
208 
209 	chandevinit();
210 	poperror();
211 	disinit("/osinit.dis");
212 }
213 
214 
215 void
216 userinit(void)
217 {
218 	Proc *p;
219 	Osenv *o;
220 
221 	p = newproc();
222 	o = p->env;
223 
224 	o->fgrp = newfgrp(nil);
225 	o->pgrp = newpgrp();
226 	kstrdup(&o->user, eve);
227 	strcpy(p->text,"interp");
228 
229 	p->fpstate = FPINIT;
230 	fpinit();
231 
232 	/*
233 	 * Kernel Stack
234 	 */
235 	p->sched.pc = (ulong)init0;
236 	p->sched.sp = (ulong)p->kstack+KSTACK-8;
237 	p->sched.sp &= ~7;		/* SP must be 8-byte aligned */
238 
239 	ready(p);
240 }
241 
242 uchar *
243 pusharg(char *p)
244 {
245 	int n;
246 
247 	n = strlen(p)+1;
248 	sp -= n;
249 	memmove(sp, p, n);
250 	return sp;
251 }
252 
253 void
254 exit(int ispanic)
255 {
256 	USED(ispanic);
257 
258 	spllo();
259 	print("cpu exiting\n");
260 
261 	/* Shutdown running devices */
262 	chandevshutdown();
263 
264 	microdelay(500);
265 	systemreset();
266 }
267 
268 void
269 reboot(void)
270 {
271 	exit(0);
272 }
273 
274 void
275 halt(void)
276 {
277 	spllo();
278 	print("cpu halted\n");
279 	microdelay(500);
280 	for(;;);
281 }
282 
283 int
284 probemem(ulong addr)
285 {
286 	ulong pcr, save0;
287 	int works;
288 
289 	save0 = getphys(0);
290 	pcr = getpcr()|NOFAULT;
291 	works = 0;
292 	setpcr(pcr & ~MEMPCHECK);
293 	putphys(addr, ~addr);
294 	if(addr)
295 		putphys(0, 0x89ABCDEF);
296 	if(getphys(addr) == ~addr){
297 		setpcr(pcr);
298 		putphys(addr, addr);
299 		if(addr)
300 			putphys(0, 0x89ABCDEF);
301 		if(getphys(addr) == addr)
302 			works = 1;
303 	}
304 	setpcr(pcr & ~NOFAULT);
305 	putphys(0, save0);
306 	getphys(AFSR);	/* clear fault status */
307 	getrmmu(SFSR);	/* clear fault status */
308 	return works;
309 }
310 
311 /*
312  * this assumes that if a bank is not empty,
313  * its first slot is filled.
314  *
315  * ../port/alloc.c and ../port/page.c
316  * need to be changed to support more than two banks.
317  */
318 void
319 scanbank(ulong base, uchar *mempres, int n)
320 {
321 	int i;
322 	ulong addr, npg;
323 
324 	npg = 0;
325 	for(i=0; i<n; i++){
326 		mempres[i] = 0;
327 		addr = base + i*MB;
328 		if(!probemem(addr))
329 			break;
330 		if(addr != base) {
331 			/* check for mirrors */
332 			putphys(addr, addr);
333 			if(getphys(base) == addr)
334 				break;
335 		}
336 		mempres[i] = 1;
337 		npg += MB/BY2PG;
338 	}
339 	if(npg){
340 		if(conf.npage0 == 0){
341 			conf.base0 = base;
342 			conf.npage0 = npg;
343 		}else if(conf.npage1 < npg){
344 			conf.base1 = base;
345 			conf.npage1 = npg;
346 		}
347 	}
348 }
349 
350 void
351 physcopyin(void *d, ulong s, int n)
352 {
353 	int i, j;
354 	ulong w;
355 
356 	for(i=0; i<n; i+=sizeof(ulong)) {
357 		w = getphys(s+i);
358 		j = n-i;
359 		if(j > sizeof(ulong))
360 			j = sizeof(ulong);
361 		memmove((uchar*)d+i, &w, j);
362 	}
363 }
364 
365 Conf	conf;
366 
367 void
368 confinit(void)
369 {
370 	ulong i;
371 	ulong ktop;
372 
373 	conf.monitor = 0;
374 
375 	conf.nmach = 1;
376 	if(conf.nmach > MAXMACH)
377 		panic("confinit");
378 
379 	/* fetch ID prom */
380 	physcopyin(&idprom, NVR_PHYS+IDOFF, sizeof(idprom));
381 	if(idprom.format!=1 || (idprom.type&0xF0)!=0x80)
382 		*(ulong*)~0 = 0;	/* not a new generation sparc; die! */
383 
384 	for(sparam = sysparam; sparam->id; sparam++)
385 		if(sparam->id == idprom.type)
386 			break;
387 
388 	/* First entry in the table is the default */
389 	if(sparam->id == 0)
390 		sparam = sysparam;
391 
392 	conf.ss2 = sparam->ss2;
393 	conf.vacsize = sparam->vacsize;
394 	conf.vaclinesize = sparam->vacline;
395 	conf.ncontext = sparam->ncontext;
396 	conf.ss2cachebug = sparam->cachebug;
397 
398 	for(i=0; i<sparam->nbank; i++)
399 		if(probemem(i*sparam->banksize*MB))
400 			scanbank(i*sparam->banksize*MB, mempres,
401 				sparam->banksize);
402 
403 	bank[0] = conf.npage0*BY2PG/MB;
404 	bank[1] = conf.npage1*BY2PG/MB;
405 
406 	if(bank[1] == 0){
407 		/*
408 		 * This split of memory into 2 banks fools the allocator into
409 		 * allocating low memory pages from bank 0 for the ethernet
410 		 * since it has only a 24bit address *counter.
411 		 * NB. Suns must have at LEAST 8Mbytes.
412 		 */
413 		conf.npage1 = conf.npage0 - (8*MB)/BY2PG;
414 		conf.base1 = conf.base0 + 8*MB;
415 		conf.npage0 = (8*MB)/BY2PG;
416 		bank[1] = bank[0]-8;
417 		bank[0] = 8;
418 	}
419 
420 	conf.npage = conf.npage0+conf.npage1;
421 
422 	ktop = PGROUND((ulong)end);
423 	ktop = PADDR(ktop);
424 	conf.npage0 -= ktop/BY2PG;
425 	conf.base0 += ktop;
426 
427 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
428 	conf.copymode = 0;		/* copy on write */
429 	conf.arp = 32;
430 	conf.ialloc = (((conf.npage*(100-sparam->pcnt))/100)/2)*BY2PG;
431 
432 	eve = strdup("inferno");
433 
434 #ifdef notdef
435         /* XXX - Eric - Autoconfigure memory */
436 	/* XXX - Tad: 8 eigths, total... */
437 	mainmem->maxsize = (conf.npage*BY2PG)/8;
438 	heapmem->maxsize = ((conf.npage*BY2PG)*5)/8;
439 	imagmem->maxsize = ((conf.npage*BY2PG)*2)/8;
440 #endif
441 }
442 
443 /*
444  *  set up the lance
445  */
446 void
447 lancesetup(Lance *lp)
448 {
449 	KMap *k;
450 	DMAdev *dma;
451 	ulong pa, va;
452 	int i;
453 
454 	k = kmappa(ETHER, PTEIO|PTENOCACHE);
455 	lp->rdp = (void*)(VA(k)+0);
456 	lp->rap = (void*)(VA(k)+2);
457 	for(i=0; i<6; i++)
458 		lp->ea[i] = idprom.ea[i];
459 
460 	lp->lognrrb = 7;
461 	lp->logntrb = 7;
462 	lp->nrrb = 1<<lp->lognrrb;
463 	lp->ntrb = 1<<lp->logntrb;
464 	lp->sep = 1;
465 	lp->busctl = BSWP | ACON | BCON;
466 
467 	/*
468 	 * Allocate area for lance init block and descriptor rings
469 	 */
470 	pa = PADDR(xspanalloc(BY2PG, BY2PG, 0));
471 
472 	/* map at LANCESEGM */
473 	va = kmapdma(pa, BY2PG);
474 	lp->lanceram = (ushort*)va;
475 	lp->lm = (Lancemem*)va;
476 
477 	/*
478 	 * Allocate space in host memory for the io buffers.
479 	 */
480 	i = (lp->nrrb+lp->ntrb)*sizeof(Lancepkt);
481 	i = (i+(BY2PG-1))/BY2PG;
482 	pa = PADDR(xspanalloc(i*BY2PG, BY2PG, 0));
483 	va = kmapdma(pa, i*BY2PG);
484 
485 	lp->lrp = (Lancepkt*)va;
486 	lp->rp = (Lancepkt*)va;
487 	lp->ltp = lp->lrp+lp->nrrb;
488 	lp->tp = lp->rp+lp->nrrb;
489 
490 	k = kmappa(DMA, PTEIO|PTENOCACHE);
491 	dma = (DMAdev*)VA(k);
492 	dma->base = 0xff;
493 
494 	/*
495 	 * for now, let's assume the ROM has left the results of its
496 	 * auto-sensing
497 	 */
498 #ifdef notdef
499 	if(dma->ecsr & E_TP_select)
500 		print("Twisted pair ethernet\n");
501 	else
502 		print("AUI ethernet\n");
503 #endif
504 	microdelay(1);
505 	dma->ecsr |= E_Int_en|E_Invalidate|E_Dsbl_wr_inval|E_Dsbl_rd_drn;
506 	microdelay(1);
507 }
508 
509 static void
510 linkproc(void)
511 {
512 	spllo();
513 	(*up->kpfun)(up->arg);
514 }
515 
516 void
517 kprocchild(Proc *p, void (*func)(void*), void *arg)
518 {
519 	p->sched.pc = (ulong)linkproc;
520 	p->sched.sp = (ulong)p->kstack+KSTACK-8;
521 
522 	p->kpfun = func;
523 	p->arg = arg;
524 }
525 
526 
527 void
528 FPsave(void *f)		/* f should be a FPenv */
529 {
530 	savefsr(f);
531 }
532 
533 void
534 FPrestore(void *f)	/* f should be a FPenv */
535 {
536 	restfsr(f);
537 }
538 
539 void
540 fpsave(FPU *f)
541 {
542 	savefpregs( f );
543 }
544 
545 void
546 fprestore(FPU *f)
547 {
548 	restfpregs(f);
549 }
550 
551 int
552 islo(void)
553 {
554 	int val;
555 	val =  (getpsr()&SPL(15)) == 0;
556 
557 	return val;
558 }
559 
560 void
561 setvec(void)
562 {
563 	/* XXX - Tad: eventually implement this */
564 }
565