#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "version.h" Mach *m = &mach0; Proc *up; int cflag; ulong cachetable[1024]; Sysint *sysintr; struct { uchar format; uchar type; uchar ea[6]; uchar pad[32-8]; } idprom; int cpuserver; ulong bank[8]; uchar mempres[64]; char fbstr[32]; ulong fbslot; int usecg6; Label catch; uchar *sp; int cold=1; 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 */ char cachebug; /* Machine needs cache bug work around */ int nbank; /* Number of banks of memory */ int banksize; /* Maximum Mbytes per bank */ int pcnt; /* percent of mem for kernel? */ } sysparam[] = { { 0xFF, "unknown Sun4M",0, 0, 0, 64, 0, 4, 32 ,0}, { 0x80, "JavaStation uSparcII",0, 0, 0, 256, 0, 4, 32 ,2}, { 0 } }; Sysparam *sparam; void doc(char *m) { print("%s\n", m); } static void poolsizeinit(void); /* XXX - Tad: hack */ void main(void) { machinit(); trapinit(); confinit(); xinit(); mmuinit(); intrinit(); clockinit(); printinit(); screeninit(); cflag=1; /* JIT baby, JIT! */ ioinit(); doc("ioinit..."); ns16552install(); poolsizeinit(); doc("ns16552install..."); kbdinit(); doc("kbdinit..."); cacheinit(); doc("cacheinit..."); procinit(); doc("procinit..."); putphys(MID, 0x1F<<16); /* enable arbitration */ links(); doc("links"); chandevreset(0); doc("chandevreset..."); print("\nInferno Network Operating System\n"); print("%s-%s \n\n",VERSION, conffile); print("JIT Compilation Mode = %d\n",cflag); userinit(); doc("userinit..."); /* clear pending processor interrupts */ putphys(PROCINTCLR, (~0<<17)|(1<<15)); print("berore schedinit\n"); schedinit(); } extern int main_pool_pcnt; extern int heap_pool_pcnt; extern int image_pool_pcnt; static void poolsizeinit(void) { ulong nb = conf.npage*BY2PG; print("Total memory available: %d K\n",nb/1024); poolsize(mainmem, (nb*main_pool_pcnt)/100, 0); poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0); poolsize(imagmem, (nb*image_pool_pcnt)/100, 1); } void intrinit(void) { KMap *k; /* clear fault status */ getphys(AFSR); k = kmappa(SYSINTR, PTEIO|PTENOCACHE); sysintr = (Sysint*)VA(k); /* mask all interrupts */ sysintr->maskset = ~0; /* allow these */ sysintr->maskclr=MaskAllIntr|MEIntr|MSIIntr|EMCIntr|EtherIntr|KbdIntr; /* clear pending processor interrupts */ putphys(PROCINTCLR, (~0<<17)|(1<<15)); } void systemreset(void) { microdelay(200); putphys(SYSCTL, getphys(SYSCTL)|1); /* power on reset */ } void machinit(void) { memset(m, 0, sizeof(Mach)); } void ioinit(void) { KMap *k; uchar *sindex; /* superio index */ uchar *sdata; /* superio data */ uchar *mkctl; /* superio mouse/kbd ctl register */ uchar *mkdata; /* superio mouse/kbd data register */ /* enable the uart's on the superio chip */ k = kmappa(SUPERIO_PHYS_PAGE, PTEIO|PTENOCACHE); sindex = (uchar*)(VA(k)+SUPERIO_INDEX_OFFSET); sdata = (uchar*)(VA(k)+SUPERIO_DATA_OFFSET); mkdata = (uchar*)(VA(k)+SUPERIO_MOUSE_KBD_DATA_PORT); mkctl = (uchar*)(VA(k)+SUPERIO_MOUSE_KBD_CTL_PORT); superioinit(VA(k),sindex,sdata,mkctl,mkdata); doc("superioinit..."); } void init0(void) { Osenv *o; up->nerrlab = 0; print("before spllo"); spllo(); print("Sun Sparc %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); if(waserror()) panic("init0"); /* from /work/brucee/ppc-19-feb/os/ibox/main.c init0() * * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. */ o = up->env; o->pgrp->slash = namec("#/", Atodir, 0, 0); o->pgrp->dot = cclone(o->pgrp->slash, 0); chandevinit(); poperror(); disinit("/osinit.dis"); } void userinit(void) { Proc *p; Osenv *o; p = newproc(); o = p->env; o->fgrp = newfgrp(); o->pgrp = newpgrp(); strcpy(o->user,eve); strcpy(p->text,"interp"); p->fpstate = FPINIT; fpinit(); /* * Kernel Stack */ p->sched.pc = (ulong)init0; p->sched.sp = (ulong)p->kstack+KSTACK-8; p->sched.sp &= ~7; /* SP must be 8-byte aligned */ ready(p); } uchar * pusharg(char *p) { int n; n = strlen(p)+1; sp -= n; memmove(sp, p, n); return sp; } void exit(int ispanic) { USED(ispanic); spllo(); print("cpu exiting\n"); /* Shutdown running devices */ chandevreset(1); microdelay(500); systemreset(); } void reboot(void) { exit(0); } void halt(void) { spllo(); print("cpu halted\n"); microdelay(500); for(;;); } int probemem(ulong addr) { ulong pcr, save0; int works; save0 = getphys(0); pcr = getpcr()|NOFAULT; works = 0; setpcr(pcr & ~MEMPCHECK); putphys(addr, ~addr); if(addr) putphys(0, 0x89ABCDEF); if(getphys(addr) == ~addr){ setpcr(pcr); putphys(addr, addr); if(addr) putphys(0, 0x89ABCDEF); if(getphys(addr) == addr) works = 1; } setpcr(pcr & ~NOFAULT); putphys(0, save0); getphys(AFSR); /* clear fault status */ getrmmu(SFSR); /* clear fault status */ return works; } /* * this assumes that if a bank is not empty, * its first slot is filled. * * /sys/src/9/port/alloc.c and /sys/src/9/port/page.c * need to be changed to support more than two banks. */ void scanbank(ulong base, uchar *mempres, int n) { int i; ulong addr, npg; npg = 0; for(i=0; i sizeof(ulong)) j = sizeof(ulong); memmove((uchar*)d+i, &w, j); } } Conf conf; void confinit(void) { ulong i; ulong ktop; conf.monitor = 0; conf.nmach = 1; if(conf.nmach > MAXMACH) panic("confinit"); /* fetch ID prom */ physcopyin(&idprom, NVR_PHYS+IDOFF, sizeof(idprom)); if(idprom.format!=1 || (idprom.type&0xF0)!=0x80) *(ulong*)~0 = 0; /* not a new generation sparc; die! */ for(sparam = sysparam; sparam->id; sparam++) if(sparam->id == idprom.type) 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.ss2cachebug = sparam->cachebug; for(i=0; inbank; i++) if(probemem(i*sparam->banksize*MB)) scanbank(i*sparam->banksize*MB, mempres, sparam->banksize); 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 = conf.base0 + 8*MB; conf.npage0 = (8*MB)/BY2PG; bank[1] = bank[0]-8; bank[0] = 8; } conf.npage = conf.npage0+conf.npage1; ktop = PGROUND((ulong)end); ktop = PADDR(ktop); conf.npage0 -= ktop/BY2PG; conf.base0 += ktop; conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; conf.copymode = 0; /* copy on write */ conf.arp = 32; conf.ialloc = (((conf.npage*(100-sparam->pcnt))/100)/2)*BY2PG; conf.interps = 5; strcpy(eve,"inferno"); #ifdef notdef /* XXX - Eric - Autoconfigure memory */ /* XXX - Tad: 8 eigths, total... */ mainmem->maxsize = (conf.npage*BY2PG)/8; heapmem->maxsize = ((conf.npage*BY2PG)*5)/8; imagmem->maxsize = ((conf.npage*BY2PG)*2)/8; #endif } /* * set up the lance */ void lancesetup(Lance *lp) { KMap *k; DMAdev *dma; ulong pa, va; int i; k = kmappa(ETHER, PTEIO|PTENOCACHE); lp->rdp = (void*)(VA(k)+0); lp->rap = (void*)(VA(k)+2); for(i=0; i<6; i++) lp->ea[i] = idprom.ea[i]; lp->lognrrb = 7; lp->logntrb = 7; 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 = PADDR(xspanalloc(BY2PG, BY2PG, 0)); /* map at LANCESEGM */ va = kmapdma(pa, BY2PG); lp->lanceram = (ushort*)va; lp->lm = (Lancemem*)va; /* * Allocate space in host memory for the io buffers. */ i = (lp->nrrb+lp->ntrb)*sizeof(Lancepkt); i = (i+(BY2PG-1))/BY2PG; pa = PADDR(xspanalloc(i*BY2PG, BY2PG, 0)); va = kmapdma(pa, i*BY2PG); lp->lrp = (Lancepkt*)va; lp->rp = (Lancepkt*)va; lp->ltp = lp->lrp+lp->nrrb; lp->tp = lp->rp+lp->nrrb; k = kmappa(DMA, PTEIO|PTENOCACHE); dma = (DMAdev*)VA(k); dma->base = 0xff; /* * for now, let's assume the ROM has left the results of its * auto-sensing */ #ifdef notdef if(dma->ecsr & E_TP_select) print("Twisted pair ethernet\n"); else print("AUI ethernet\n"); #endif microdelay(1); dma->ecsr |= E_Int_en|E_Invalidate|E_Dsbl_wr_inval|E_Dsbl_rd_drn; microdelay(1); } static void linkproc(void) { spllo(); (*up->kpfun)(up->arg); } void kprocchild(Proc *p, void (*func)(void*), void *arg) { p->sched.pc = (ulong)linkproc; p->sched.sp = (ulong)p->kstack+KSTACK-8; p->kpfun = func; p->arg = arg; } void FPsave(void *f) /* f should be a FPenv */ { savefsr(f); } void FPrestore(void *f) /* f should be a FPenv */ { restfsr(f); } void fpsave(FPU *f) { savefpregs( f ); } void fprestore(FPU *f) { restfpregs(f); } int islo(void) { int val; val = (getpsr()&SPL(15)) == 0; return val; } void setvec(void) { /* XXX - Tad: eventually implement this */ }