#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "init.h" /* * args passed by boot process */ int _argc; char **_argv; char **_env; /* * arguments passed to initcode and /boot */ char argbuf[128]; /* * environment passed to boot -- sysname, consname, diskid */ char consname[NAMELEN]; char bootdisk[NAMELEN]; char screenldepth[NAMELEN]; /* * software tlb simulation */ Softtlb stlb[MAXMACH][STLBSIZE]; Conf conf; FPsave initfp; void main(void) { tlbinit(); /* Very early to establish IO mappings */ ioinit(1); arginit(); confinit(); savefpregs(&initfp); machinit(); kmapinit(); xinit(); iomapinit(); printinit(); serialinit(); vecinit(); screeninit(); iprint("\n\nBrazil\n"); pageinit(); procinit0(); initseg(); links(); chandevreset(); swapinit(); userinit(); schedinit(); } /* * copy arguments passed by the boot kernel (or ROM) into a temporary buffer. * we do this because the arguments are in memory that may be allocated * to processes or kernel buffers. * * also grab any environment variables that might be useful */ struct { char *name; char *val; }bootenv[] = { {"netaddr=", sysname}, {"console=", consname}, {"bootdisk=", bootdisk}, {"ldepth=", screenldepth}, }; char *sp; char * pusharg(char *p) { int n; n = strlen(p)+1; sp -= n; memmove(sp, p, n); return sp; } void arginit(void) { int i, n; char **av; /* * get boot env variables */ if(*sysname == 0) for(av = _env; *av; av++) for(i=0; i < sizeof bootenv/sizeof bootenv[0]; i++){ n = strlen(bootenv[i].name); if(strncmp(*av, bootenv[i].name, n) == 0){ strncpy(bootenv[i].val, (*av)+n, NAMELEN); bootenv[i].val[NAMELEN-1] = '\0'; break; } } /* * pack args into buffer */ av = (char**)argbuf; sp = argbuf + sizeof(argbuf); for(i = 0; i < _argc; i++){ if(strchr(_argv[i], '=')) break; av[i] = pusharg(_argv[i]); } av[i] = 0; } /* * initialize a processor's mach structure. each processor does this * for itself. */ void machinit(void) { int n; /* Ensure CU1 is off */ clrfpintr(); /* scrub cache */ cleancache(); memset(m, 0, sizeof(Mach)); n = m->machno; m->stb = &stlb[n][0]; m->speed = 50; clockinit(); active.exiting = 0; active.machs = 1; } /* * Set up a console on serial port 2 */ void serialinit(void) { NS16552setup(Uart1, UartFREQ); NS16552special(0, 9600, &kbdq, &printq, kbdcr2nl); kbdinit(); } /* * Map IO address space in wired down TLB entry 1 */ void ioinit(int mapeisa) { ulong devphys, isaphys, intphys, isamphys; /* * If you want to segattach the eisa space these * mappings must be turned off to prevent duplication * of the tlb entries */ if(mapeisa) { isaphys = IOPTE|PPN(Eisaphys)|PTEGLOBL; isamphys = 0x04000000|IOPTE|PTEGLOBL; } else { isaphys = PTEGLOBL; isamphys = PTEGLOBL; } /* * Map devices and the Eisa control space */ devphys = IOPTE|PPN(Devicephys); puttlbx(1, Devicevirt, devphys, isaphys, PGSZ64K); /* * Map Interrupt control & Eisa memory */ intphys = IOPTE|PPN(Intctlphys); puttlbx(2, Intctlvirt, intphys, isamphys, PGSZ1M); /* Enable all devce interrupt */ IO(ushort, Intenareg) = 0xffff; /* Look at the first 16M of Eisa memory */ /* IO(uchar, EisaLatch) = 0; /**/ } /* * Pull the ethernet address out of NVRAM */ void enetaddr(uchar *ea) { int i; uchar tbuf[8]; for(i = 0; i < 8; i++) tbuf[i] = ((uchar*)(NvramRO+Enetoffset))[i]; print("ether:"); for(i = 0; i < 6; i++) { ea[i] = tbuf[7-i]; print("%2.2ux", ea[i]); } print("\n"); } /* * All DMA and ether IO buffers must reside in the first 16M bytes of * memory to be covered by the translation registers */ void iomapinit(void) { int i; Tte *t; t = xspanalloc(Ntranslation*sizeof(Tte), BY2PG, 0); for(i = 0; i < Ntranslation; i++) t[i].lo = i<slash = namec("#/", Atodir, 0, 0); up->dot = clone(up->slash, 0); iallocinit(); chandevinit(); if(!waserror()){ ksetenv("cputype", "mips"); sprint(buf, "carrera %s R4400PC", conffile); ksetenv("terminal", buf); ksetenv("sysname", sysname); poperror(); } kproc("alarm", alarmkproc, 0); touser((uchar*)(USTKTOP-sizeof(argbuf))); } void userinit(void) { Proc *p; KMap *k; Page *pg; char **av; Segment *s; 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); p->fpstate = FPinit; p->fpsave.fpstatus = initfp.fpstatus; /* * Kernel Stack */ p->sched.pc = (ulong)init0; p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD; /* * User Stack, pass input arguments to boot process */ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); p->seg[SSEG] = s; pg = newpage(1, 0, USTKTOP-BY2PG); segpage(s, pg); k = kmap(pg); for(av = (char**)argbuf; *av; av++) *av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf; memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf); kunmap(k); /* Text */ s = newseg(SG_TEXT, UTZERO, 1); s->flushme++; p->seg[TSEG] = s; pg = newpage(1, 0, UTZERO); memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); segpage(s, pg); k = kmap(s->map[0]->pages[0]); memmove((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); ready(p); } void exit(long type) { USED(type); spllo(); print("cpu %d exiting\n", m->machno); while(consactive()) delay(10); splhi(); for(;;) ; } void confinit(void) { ulong ktop, top; ktop = PGROUND((ulong)end); ktop = PADDR(ktop); top = (16*1024*1024)/BY2PG; conf.base0 = 0; conf.npage0 = top; conf.npage = conf.npage0; conf.npage0 -= ktop/BY2PG; conf.base0 += ktop; conf.npage1 = 0; conf.base1 = 0; conf.upages = (conf.npage*70)/100; conf.nmach = 1; /* set up other configuration parameters */ conf.nproc = 100; conf.nswap = conf.npage*3; conf.nimage = 200; conf.ipif = 8; conf.ip = 64; conf.arp = 32; conf.frag = 32; conf.monitor = 1; conf.copymode = 0; /* copy on write */ } /* * for the sake of devcons */ void buzz(int f, int d) { USED(f); USED(d); }