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