summaryrefslogtreecommitdiff
path: root/sys/src/9/mtx/main.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/mtx/main.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/mtx/main.c')
-rwxr-xr-xsys/src/9/mtx/main.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/sys/src/9/mtx/main.c b/sys/src/9/mtx/main.c
new file mode 100755
index 000000000..eebad4444
--- /dev/null
+++ b/sys/src/9/mtx/main.c
@@ -0,0 +1,465 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "pool.h"
+
+Conf conf;
+FPsave initfp;
+
+void
+main(void)
+{
+ memset(edata, 0, (ulong)end-(ulong)edata);
+ conf.nmach = 1;
+ machinit();
+ ioinit();
+ i8250console();
+ quotefmtinstall();
+ print("\nPlan 9\n");
+ confinit();
+ xinit();
+ raveninit();
+ trapinit();
+ printinit();
+ cpuidprint();
+ mmuinit();
+ hwintrinit();
+ clockinit();
+ kbdinit();
+ procinit0();
+ initseg();
+ timersinit();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ fpsave(&initfp);
+ initfp.fpscr = 0;
+ userinit();
+ schedinit();
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(Mach));
+ m->cputype = getpvr()>>16;
+
+ /*
+ * For polled uart output at boot, need
+ * a default delay constant. 100000 should
+ * be enough for a while. Cpuidentify will
+ * calculate the real value later.
+ */
+ m->loopconst = 100000;
+
+ /* turn on caches */
+ puthid0(gethid0() | BIT(16) | BIT(17));
+
+ active.machs = 1;
+ active.exiting = 0;
+}
+
+void
+cpuidprint(void)
+{
+ char *id;
+
+ id = "unknown PowerPC";
+ switch(m->cputype) {
+ case 9:
+ id = "PowerPC 604e";
+ break;
+ }
+ print("cpu0: %s\n", id);
+}
+
+static struct
+{
+ char *name;
+ char *val;
+}
+plan9ini[] =
+{
+ { "console", "0" },
+ { "ether0", "type=2114x" },
+};
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nelem(plan9ini); i++)
+ if(cistrcmp(name, plan9ini[i].name) == 0)
+ return plan9ini[i].val;
+ return nil;
+}
+
+void
+init0(void)
+{
+// char **p, *q, name[KNAMELEN];
+// int n;
+ char buf[2*KNAMELEN];
+
+ 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()){
+ snprint(buf, sizeof(buf), "power %s mtx", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("cputype", "power", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+/*
+ for(p = confenv; *p; p++) {
+ q = strchr(p[0], '=');
+ if(q == 0)
+ continue;
+ n = q-p[0];
+ if(n >= KNAMELEN)
+ n = KNAMELEN-1;
+ memmove(name, p[0], n);
+ name[n] = 0;
+ if(name[0] != '*')
+ ksetenv(name, q+1, 0);
+ ksetenv(name, q+1, 1);
+ }
+*/
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ kproc("mmusweep", mmusweep, 0);
+ touser((void*)(USTKTOP-8));
+}
+
+void
+userinit(void)
+{
+ Proc *p;
+ Segment *s;
+ KMap *k;
+ Page *pg;
+
+ 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);
+
+ p->fpstate = FPinit;
+
+ /*
+ * Kernel Stack
+ *
+ * N.B. The -12 for the stack pointer is important.
+ * 4 bytes for gotolabel's return PC
+ */
+ 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);
+
+ /*
+ * 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);
+}
+
+/* still to do */
+void
+reboot(void*, void*, ulong)
+{
+ exit(0);
+}
+
+void
+exit(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ print("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic && m->machno == 0){
+ if(cpuserver)
+ delay(10000);
+ else if(conf.monitor)
+ for(;;);
+ }
+ else
+ delay(1000);
+
+ watchreset();
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ if(p->fpstate == FPactive){
+ if(p->state != Moribund)
+ fpsave(&up->fpsave);
+ p->fpstate = FPinactive;
+ }
+}
+
+void
+confinit(void)
+{
+ char *p;
+ int userpcnt;
+ ulong pa, kpages;
+ extern ulong memsize; /* passed in from ROM monitor */
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ pa = PGROUND(PADDR(end));
+
+ conf.mem[0].npage = memsize/BY2PG;
+ conf.mem[0].base = pa;
+ conf.npage = conf.mem[0].npage;
+
+ conf.nmach = 1;
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 2000)
+ conf.nproc = 2000;
+ conf.nimage = 200;
+ conf.nswap = conf.nproc*80;
+ conf.nswppo = 4096;
+ conf.copymode = 0; /* copy on write */
+
+ if(cpuserver) {
+ if(userpcnt < 10)
+ userpcnt = 70;
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Hack for the big boys. Only good while physmem < 4GB.
+ * Give the kernel a max. of 16MB + enough to allocate the
+ * page pool.
+ * This is an overestimate as conf.upages < conf.npages.
+ * The patch of nimage is a band-aid, scanning the whole
+ * page list in imagereclaim just takes too long.
+ */
+ if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
+ kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
+ conf.nimage = 2000;
+ kpages += (conf.nproc*KSTACK)/BY2PG;
+ }
+ } else {
+ if(userpcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ userpcnt = 40;
+ else
+ userpcnt = 60;
+ }
+ kpages = conf.npage - (conf.npage*userpcnt)/100;
+
+ /*
+ * Make sure terminals with low memory get at least
+ * 4MB on the first Image chunk allocation.
+ */
+ if(conf.npage*BY2PG < 16*MB)
+ imagmem->minarena = 4*1024*1024;
+ }
+ conf.upages = conf.npage - kpages;
+ conf.ialloc = (kpages/2)*BY2PG;
+
+ /*
+ * Guess how much is taken by the large permanent
+ * datastructures. Mntcache and Mntrpc are not accounted for
+ * (probably ~300KB).
+ */
+ kpages *= BY2PG;
+ kpages -= conf.upages*sizeof(Page)
+ + conf.nproc*sizeof(Proc)
+ + conf.nimage*sizeof(Image)
+ + conf.nswap
+ + conf.nswppo*sizeof(Page);
+ mainmem->maxsize = kpages;
+ if(!cpuserver){
+ /*
+ * give terminals lots of image memory, too; the dynamic
+ * allocation will balance the load properly, hopefully.
+ * be careful with 32-bit overflow.
+ */
+ imagmem->maxsize = kpages;
+ }
+
+// conf.monitor = 1; /* BUG */
+}
+
+static int
+getcfields(char* lp, char** fields, int n, char* sep)
+{
+ int i;
+
+ for(i = 0; lp && *lp && i < n; i++){
+ while(*lp && strchr(sep, *lp) != 0)
+ *lp++ = 0;
+ if(*lp == 0)
+ break;
+ fields[i] = lp;
+ while(*lp && strchr(sep, *lp) == 0){
+ if(*lp == '\\' && *(lp+1) == '\n')
+ *lp++ = ' ';
+ lp++;
+ }
+ }
+
+ return i;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ int i;
+ char cc[KNAMELEN], *p;
+
+ sprint(cc, "%s%d", class, ctlrno);
+
+ p = getconf(cc);
+ if(p == 0)
+ return 0;
+ isa->nopt = tokenize(p, isa->opt, NISAOPT);
+ for(i = 0; i < isa->nopt; i++){
+ p = isa->opt[i];
+ if(cistrncmp(p, "type=", 5) == 0)
+ isa->type = p + 5;
+ else if(cistrncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(cistrncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(cistrncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ }
+ return 1;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
+
+int
+cistrncmp(char *a, char *b, int n)
+{
+ unsigned ac, bc;
+
+ while(n > 0){
+ ac = *a++;
+ bc = *b++;
+ n--;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+
+ return 0;
+}