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
doc(char * m)57 doc(char *m)
58 {
59 print("%s\n", m);
60 }
61
62 static void poolsizeinit(void);
63
64 void
main(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
poolsizeinit(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
intrinit(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
systemreset(void)147 systemreset(void)
148 {
149 microdelay(200);
150 putphys(SYSCTL, getphys(SYSCTL)|1); /* power on reset */
151 }
152
153 void
machinit(void)154 machinit(void)
155 {
156 memset(m, 0, sizeof(Mach));
157 }
158
159 void
ioinit(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
init0(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
userinit(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 *
pusharg(char * p)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
exit(int ispanic)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
reboot(void)269 reboot(void)
270 {
271 exit(0);
272 }
273
274 void
halt(void)275 halt(void)
276 {
277 spllo();
278 print("cpu halted\n");
279 microdelay(500);
280 for(;;);
281 }
282
283 int
probemem(ulong addr)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
scanbank(ulong base,uchar * mempres,int n)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
physcopyin(void * d,ulong s,int n)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
confinit(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
lancesetup(Lance * lp)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
linkproc(void)510 linkproc(void)
511 {
512 spllo();
513 (*up->kpfun)(up->arg);
514 }
515
516 void
kprocchild(Proc * p,void (* func)(void *),void * arg)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
FPsave(void * f)528 FPsave(void *f) /* f should be a FPenv */
529 {
530 savefsr(f);
531 }
532
533 void
FPrestore(void * f)534 FPrestore(void *f) /* f should be a FPenv */
535 {
536 restfsr(f);
537 }
538
539 void
fpsave(FPU * f)540 fpsave(FPU *f)
541 {
542 savefpregs( f );
543 }
544
545 void
fprestore(FPU * f)546 fprestore(FPU *f)
547 {
548 restfpregs(f);
549 }
550
551 int
islo(void)552 islo(void)
553 {
554 int val;
555 val = (getpsr()&SPL(15)) == 0;
556
557 return val;
558 }
559
560 void
setvec(void)561 setvec(void)
562 {
563 /* XXX - Tad: eventually implement this */
564 }
565