#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "init.h" #include #include uchar *intrreg; uchar idprom[32]; ulong rom; /* open boot rom vector */ int cpuserver; ulong romputcxsegm; ulong bank[2]; char mempres[256]; char fbstr[32]; ulong fbslot; Label catch; typedef struct Sysparam Sysparam; struct Sysparam { int id; /* Model type from id prom */ char *name; /* System name */ char ss2; /* Is Sparcstation 2? */ int vacsize; /* Cache size */ int vacline; /* Cache line size */ int ncontext; /* Number of MMU contexts */ int npmeg; /* Number of page map entry groups */ char cachebug; /* Machine needs cache bug work around */ int memscan; /* Number of Meg to scan looking for memory */ } sysparam[] = { { 0x51, "1 4/60", 0, 65536, 16, 8, 128, 0, 64 }, { 0x52, "IPC 4/40", 0, 65536, 16, 8, 128, 0, 64 }, { 0x53, "1+ 4/65", 0, 65536, 16, 8, 128, 0, 64 }, { 0x54, "SLC 4/20", 0, 65536, 16, 8, 128, 0, 64 }, { 0x55, "2 4/75", 1, 65536, 32, 16, 256, 1, 64 }, { 0x56, "ELC 4/25", 1, 65536, 32, 8, 128, 1, 64 }, { 0x57, "IPX 4/50", 1, 65536, 32, 8, 256, 1, 64 }, { 0 } }; Sysparam *sparam; void main(void) { u = 0; memset(edata, 0, (char*)end-(char*)edata); machinit(); active.exiting = 0; active.machs = 1; trapinit(); confinit(); xinit(); mmuinit(); kmapinit(); if(conf.monitor) screeninit(fbstr, fbslot); printinit(); ioinit(); if(conf.monitor == 0) sccspecial(2, &printq, &kbdq, 9600); pageinit(); cacheinit(); intrinit(); procinit0(); initseg(); chandevreset(); streaminit(); swapinit(); userinit(); clockinit(); schedinit(); } void intrinit(void) { KMap *k; k = kmappa(INTRREG, PTEIO|PTENOCACHE); intrreg = (uchar*)k->va; } void systemreset(void) { delay(200); putenab(ENABRESET); } void machinit(void) { int n; n = m->machno; memset(m, 0, sizeof(Mach)); m->machno = n; m->mmask = 1<machno; m->fpstate = FPinit; } void ioinit(void) { KMap *k; /* tell scc driver its addresses */ k = kmappa(KMDUART, PTEIO|PTENOCACHE); sccsetup((void*)(k->va), KMFREQ); k = kmappa(EIADUART, PTEIO|PTENOCACHE); sccsetup((void*)(k->va), EIAFREQ); /* scc port 0 is the keyboard */ sccspecial(0, 0, &kbdq, 2400); kbdq.putc = kbdstate; /* scc port 1 is the mouse */ sccspecial(1, 0, &mouseq, 2400); } void init0(void) { u->nerrlab = 0; m->proc = u->p; u->p->state = Running; u->p->mach = m; spllo(); print("Sun Sparcstation %s\n", sparam->name); print("bank 0: %dM 1: %dM\n", bank[0], bank[1]); print("frame buffer id %lux slot %ld %s\n", conf.monitor, fbslot, fbstr); u->slash = (*devtab[0].attach)(0); u->dot = clone(u->slash, 0); kproc("alarm", alarmkproc, 0); chandevinit(); if(!waserror()){ ksetterm("sun %s"); ksetenv("cputype", "sparc"); poperror(); } touser(USTKTOP-(1+MAXSYSARG)*BY2WD); } FPsave *initfpp; uchar initfpa[sizeof(FPsave)+7]; void userinit(void) { Proc *p; Segment *s; User *up; KMap *k; ulong l; 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); /* must align initfpp to an ODD word boundary */ l = (ulong)initfpa; l += 3; l &= ~7; l += 4; initfpp = (FPsave*)l; savefpregs(initfpp); p->fpstate = FPinit; /* * Kernel Stack */ p->sched.pc = (((ulong)init0) - 8); /* 8 because of RETURN in gotolabel */ p->sched.sp = USERADDR+BY2PG-(1+MAXSYSARG)*BY2WD; p->sched.sp &= ~7; /* SP must be 8-byte aligned */ p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); /* * User */ k = kmap(p->upage); up = (User*)VA(k); up->p = p; kunmap(k); /* * User Stack */ s = newseg(SG_STACK, USTKTOP-BY2PG, 1); p->seg[SSEG] = s; /* * Text */ s = newseg(SG_TEXT, UTZERO, 1); p->seg[TSEG] = s; segpage(s, newpage(1, 0, UTZERO)); k = kmap(s->map[0]->pages[0]); memmove((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); ready(p); } void exit(int ispanic) { int i; u = 0; spllo(); print("cpu %d exiting\n", m->machno); while(consactive()) for(i=0; i<1000; i++) ; splhi(); if(ispanic) for(;;); systemreset(); } void scanmem(char *mempres, int n) { int i; ulong va, addr; va = 1*MB-2*BY2PG; for(i=0; i MAXMACH) panic("confinit"); /* map id prom */ va = 1*MB-BY2PG; putw4(va, PPN(EEPROM)|PTEPROBEIO); memmove(idprom, (char*)(va+0x7d8), 32); if(idprom[0]!=1 || (idprom[1]&0xF0)!=0x50) *(ulong*)va = 0; /* not a sparcstation; die! */ putw4(va, INVALIDPTE); /* * Look for a frame buffer. Do it the way the * ROM does it: scan the slots in a specified order and use * the first one it finds. * * If we find a frame buffer, we always use it as a console * rather than the attached terminal, if any. This means * if you have a frame buffer you'd better have a builtin * keyboard, too. */ switch(idprom[1]){ case 0x52: /* IPC */ case 0x54: /* SLC */ conf.monitor = 1; fbslot = 3; strcpy(fbstr, "bwtwo"); break; case 0x57: /* IPX */ conf.monitor = 1; fbslot = 3; strcpy(fbstr, "cgsix"); break; default: /* map frame buffer id in SBUS slots 0..3 */ for(f=0; f<=3 && fbstr[0]==0; f++){ putw4(va, ((FRAMEBUFID(f)>>PGSHIFT)&0xFFFF)|PTEPROBEIO); conf.monitor = 0; /* if frame buffer not present, we will trap, so prepare to catch it */ if(setlabel(&catch) == 0){ conf.monitor = *(ulong*)va; switch(conf.monitor & 0xF0FFFFFF){ case 0xF0010101: strcpy(fbstr, "cgthree"); break; case 0xF0010104: strcpy(fbstr, "bwtwo"); break; } if(fbstr[0] == 0){ j = *(ulong*)(va+4); if(j > BY2PG-8) j = BY2PG - 8; /* -8 for safety */ for(i=0; iid; sparam++) if(sparam->id == idprom[1]) break; /* First entry in the table is the default */ if(sparam->id == 0) sparam = sysparam; conf.ss2 = sparam->ss2; conf.vacsize = sparam->vacsize; conf.vaclinesize = sparam->vacline; conf.ncontext = sparam->ncontext; conf.npmeg = sparam->npmeg; conf.ss2cachebug = sparam->cachebug; /* Chart memory */ scanmem(mempres, sparam->memscan); /* Find mirrors and allocate banks */ for(i=0; imemscan; i++) if(mempres[i]){ v = mempres[i]; for(j=i+1; jmemscan && mempres[j]>v; j++) v = mempres[j]; npg = ((v+1)-mempres[i])*MB/BY2PG; if(conf.npage0 == 0){ conf.base0 = i*MB; conf.npage0 = npg; }else if(conf.npage1 < npg){ conf.base1 = i*MB; conf.npage1 = npg; } i = v-'0'; } bank[0] = conf.npage0*BY2PG/MB; bank[1] = conf.npage1*BY2PG/MB; if(bank[1] == 0){ /* * This split of memory into 2 banks fools the allocator into * allocating low memory pages from bank 0 for the ethernet since * it has only a 24bit address counter. * NB. Suns must have at LEAST 8Mbytes. */ conf.npage1 = conf.npage0 - (8*MB)/BY2PG; conf.base1 = 8*MB; conf.npage0 = (8*MB)/BY2PG; conf.base0 = 0; bank[1] = bank[0]-8; bank[0] = 8; } conf.npage = conf.npage0+conf.npage1; conf.upages = (conf.npage*70)/100; if(cpuserver){ i = conf.npage-conf.upages; if(i > (12*MB)/BY2PG) conf.upages += i - ((12*MB)/BY2PG); } romputcxsegm = *(ulong*)(rom+260); ktop = PGROUND((ulong)end); ktop = PADDR(ktop); conf.npage0 -= ktop/BY2PG; conf.base0 += ktop; mbytes = (conf.npage*BY2PG)>>20; mul = 1 + (mbytes+11)/12; if(mul > 2) mul = 2; conf.nproc = 50*mul; if(cpuserver) conf.nswap = conf.npage*2; else conf.nswap = 4096; conf.nimage = 50; conf.copymode = 0; /* copy on write */ conf.ipif = 8; conf.ip = 64; conf.arp = 32; conf.frag = 32; if(cpuserver) conf.nproc = 500; } /* * set up the lance */ void lancesetup(Lance *lp) { KMap *k; uchar *cp; ulong pa, va; int i; k = kmappa(ETHER, PTEIO|PTENOCACHE); lp->rdp = (void*)(k->va+0); lp->rap = (void*)(k->va+2); k = kmappa(EEPROM, PTEIO|PTENOCACHE); cp = (uchar*)(k->va+0x7da); for(i=0; i<6; i++) lp->ea[i] = *cp++; kunmap(k); lp->lognrrb = 7; lp->logntrb = 5; lp->nrrb = 1<lognrrb; lp->ntrb = 1<logntrb; lp->sep = 1; lp->busctl = BSWP | ACON | BCON; /* * Allocate area for lance init block and descriptor rings */ pa = (ulong)xspanalloc(BY2PG, BY2PG, 0); /* map at LANCESEGM */ k = kmappa(pa, PTEMAINMEM|PTENOCACHE); lp->lanceram = (ushort*)k->va; lp->lm = (Lancemem*)k->va; /* * Allocate space in host memory for the io buffers. * Allocate a block and kmap it page by page. kmap's are initially * in reverse order so rearrange them. */ i = (lp->nrrb+lp->ntrb)*sizeof(Etherpkt); i = (i+(BY2PG-1))/BY2PG; pa = (ulong)xspanalloc(i*BY2PG, BY2PG, 0)&~KZERO; va = kmapregion(pa, i*BY2PG, PTEMAINMEM|PTENOCACHE); lp->lrp = (Etherpkt*)va; lp->rp = (Etherpkt*)va; lp->ltp = lp->lrp+lp->nrrb; lp->tp = lp->rp+lp->nrrb; }