#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "init.h" #include "pool.h" Mach *m; Proc *up; Conf conf; int noprint; void main(void) { mmuinvalidate(); /* zero out bss */ memset(edata, 0, end-edata); /* point to Mach structure */ m = (Mach*)MACHADDR; memset(m, 0, sizeof(Mach)); m->ticks = 1; active.machs = 1; rs232power(1); quotefmtinstall(); iprint("\nPlan 9 bitsy kernel\n"); confinit(); xinit(); mmuinit(); machinit(); trapinit(); sa1110_uartsetup(1); dmainit(); screeninit(); printinit(); /* from here on, print works, before this we need iprint */ clockinit(); procinit0(); initseg(); links(); chandevreset(); pageinit(); swapinit(); userinit(); powerinit(); schedinit(); } /* need to do better */ void reboot(void*, void*, ulong) { exit(0); } /* * exit kernel either on a panic or user request */ void exit(int ispanic) { void (*f)(void); USED(ispanic); delay(1000); iprint("it's a wonderful day to die\n"); cacheflush(); mmuinvalidate(); mmudisable(); f = nil; (*f)(); } static uchar *sp; /* * starting place for first process */ void init0(void) { up->nerrlab = 0; spllo(); /* * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. */ up->slash = namec("#/", Atodir, 0, 0); pathclose(up->slash->path); up->slash->path = newpath("/"); up->dot = cclone(up->slash); chandevinit(); if(!waserror()){ ksetenv("terminal", "bitsy", 0); ksetenv("cputype", "arm", 0); if(cpuserver) ksetenv("service", "cpu", 0); else ksetenv("service", "terminal", 0); poperror(); } kproc("alarm", alarmkproc, 0); kproc("power", powerkproc, 0); touser(sp); } /* * pass boot arguments to /boot */ static uchar * pusharg(char *p) { int n; n = strlen(p)+1; sp -= n; memmove(sp, p, n); return sp; } static void bootargs(ulong base) { int i, ac; uchar *av[32]; uchar *bootpath; uchar **lsp; /* * the sizeof(Sargs) is to make the validaddr check in * trap.c's syscall() work even when we have less than the * max number of args. */ sp = (uchar*)base + BY2PG - sizeof(Sargs); bootpath = pusharg("/boot/boot"); ac = 0; av[ac++] = pusharg("boot"); /* 4 byte word align stack */ sp = (uchar*)((ulong)sp & ~3); /* build argc, argv on stack */ sp -= (ac+1)*sizeof(sp); lsp = (uchar**)sp; for(i = 0; i < ac; i++) *lsp++ = av[i] + ((USTKTOP - BY2PG) - base); *lsp = 0; /* push argv onto stack */ sp -= BY2WD; lsp = (uchar**)sp; *lsp = sp + BY2WD + ((USTKTOP - BY2PG) - base); /* push pointer to "/boot" */ sp -= BY2WD; lsp = (uchar**)sp; *lsp = bootpath + ((USTKTOP - BY2PG) - base); /* leave space for where the initcode's caller's return PC would normally reside */ sp -= BY2WD; /* relocate stack to user's virtual addresses */ sp += (USTKTOP - BY2PG) - base; } /* * create the first process */ void userinit(void) { Proc *p; Segment *s; KMap *k; Page *pg; /* no processes yet */ up = nil; p = newproc(); p->pgrp = newpgrp(); p->egrp = smalloc(sizeof(Egrp)); p->egrp->ref = 1; p->fgrp = dupfgrp(nil); p->rgrp = newrgrp(); p->procmode = 0640; kstrdup(&eve, ""); kstrdup(&p->text, "*init*"); kstrdup(&p->user, eve); /* * Kernel Stack */ p->sched.pc = (ulong)init0; p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD); /* * User Stack */ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); p->seg[SSEG] = s; pg = newpage(1, 0, USTKTOP-BY2PG); segpage(s, pg); k = kmap(pg); bootargs(VA(k)); kunmap(k); /* * Text */ s = newseg(SG_TEXT, UTZERO, 1); 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); } /* * set mach dependent process state for a new process */ void procsetup(Proc *p) { p->fpstate = FPinit; } /* * Save the mach dependent part of the process state. */ void procsave(Proc *p) { USED(p); } /* place holder */ /* * dummy since rdb is not included */ void rdb(void) { } /* * probe the last location in a meg of memory, make sure it's not * reflected into something else we've already found. */ int probemem(ulong addr) { int i; ulong *p; ulong a; addr += OneMeg - sizeof(ulong); p = (ulong*)addr; *p = addr; for(i=0; i= conf.mem[i].base && ktop <= conf.mem[i].limit) conf.mem[i].base = ktop; /* zero memory */ memset((void*)conf.mem[i].base, 0, conf.mem[i].limit - conf.mem[i].base); conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG; conf.npage += conf.mem[i].npage; } if(conf.npage > 16*MB/BY2PG){ conf.upages = (conf.npage*60)/100; imagmem->minarena = 4*1024*1024; }else conf.upages = (conf.npage*40)/100; conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; /* only one processor */ conf.nmach = 1; /* set up other configuration parameters */ conf.nproc = 100; conf.nswap = conf.npage*3; conf.nswppo = 4096; conf.nimage = 200; conf.monitor = 1; conf.copymode = 0; /* copy on write */ } GPIOregs *gpioregs; ulong *egpioreg = (ulong*)EGPIOREGS; PPCregs *ppcregs; MemConfRegs *memconfregs; PowerRegs *powerregs; ResetRegs *resetregs; /* * configure the machine */ void machinit(void) { /* set direction of SA1110 io pins and select alternate functions for some */ gpioregs = mapspecial(GPIOREGS, sizeof(GPIOregs)); gpioregs->direction = GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o |GPIO_CLK_SET0_o|GPIO_CLK_SET1_o |GPIO_L3_SDA_io|GPIO_L3_MODE_o|GPIO_L3_SCLK_o |GPIO_COM_RTS_o; gpioregs->rising = 0; gpioregs->falling = 0; gpioregs->altfunc |= GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o |GPIO_SSP_CLK_i; /* map in special H3650 io pins */ egpioreg = mapspecial(EGPIOREGS, sizeof(ulong)); /* map in peripheral pin controller (ssp will need it) */ ppcregs = mapspecial(PPCREGS, sizeof(PPCregs)); /* SA1110 power management */ powerregs = mapspecial(POWERREGS, sizeof(PowerRegs)); /* memory configuraton */ memconfregs = mapspecial(MEMCONFREGS, sizeof(MemConfRegs)); /* reset controller */ resetregs = mapspecial(RESETREGS, sizeof(ResetRegs)); } /* * manage egpio bits */ static ulong egpiosticky; void egpiobits(ulong bits, int on) { if(on) egpiosticky |= bits; else egpiosticky &= ~bits; *egpioreg = egpiosticky; } void rs232power(int on) { egpiobits(EGPIO_rs232_power, on); delay(50); } void audioamppower(int on) { egpiobits(EGPIO_audio_power, on); delay(50); } void audioicpower(int on) { egpiobits(EGPIO_audio_ic_power, on); delay(50); } void irpower(int on) { egpiobits(EGPIO_ir_power, on); delay(50); } void lcdpower(int on) { egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on); delay(50); } void flashprogpower(int on) { egpiobits(EGPIO_prog_flash, on); } /* here on hardware reset */ void resettrap(void) { } /* * for drivers that used to run on x86's */ void outb(ulong a, uchar v) { *(uchar*)a = v; } void outs(ulong a, ushort v) { *(ushort*)a = v; } void outss(ulong a, void *p, int n) { ushort *sp = p; while(n-- > 0) *(ushort*)a = *sp++; } void outl(ulong a, ulong v) { *(ulong*)a = v; } uchar inb(ulong a) { return *(uchar*)a; } ushort ins(ulong a) { return *(ushort*)a; } void inss(ulong a, void *p, int n) { ushort *sp = p; while(n-- > 0) *sp++ = *(ushort*)a; } ulong inl(ulong a) { return *(ulong*)a; } char* getconf(char*) { return nil; } long _xdec(long *p) { int x; long v; x = splhi(); v = --*p; splx(x); return v; } void _xinc(long *p) { int x; x = splhi(); ++*p; splx(x); }