summaryrefslogtreecommitdiff
path: root/sys/src/9/ppc/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/ppc/main.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/ppc/main.c')
-rwxr-xr-xsys/src/9/ppc/main.c511
1 files changed, 511 insertions, 0 deletions
diff --git a/sys/src/9/ppc/main.c b/sys/src/9/ppc/main.c
new file mode 100755
index 000000000..380d6fd6f
--- /dev/null
+++ b/sys/src/9/ppc/main.c
@@ -0,0 +1,511 @@
+#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"
+#include "tos.h"
+
+#define MAXCONF 64
+
+typedef struct Plan9ini Plan9ini;
+struct Plan9ini
+{
+ char *name;
+ char *val;
+};
+
+char *plan9inistr;
+Plan9ini plan9ini[MAXCONF];
+int nconf;
+
+Conf conf;
+FPsave initfp;
+Lock testlock;
+
+static void plan9iniinit(void);
+
+char *
+cpuid(void)
+{
+ char *id;
+
+ id = "unknown PowerPC";
+ switch(m->cputype) {
+ case 8:
+ id = "PowerPC 750";
+ break;
+ case 9:
+ id = "PowerPC 604e";
+ break;
+ case 0x81:
+ id = "PowerPC 8260";
+ break;
+ case 0x8081:
+ id = "PowerPC 826xA";
+ break;
+ default:
+ break;
+ }
+ return id;
+}
+
+void
+cpuidprint(void)
+{
+ print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n",
+ cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz);
+}
+
+void
+main(void)
+{
+ memset(edata, 0, (ulong)end-(ulong)edata);
+ conf.nmach = 1;
+ machinit();
+ confinit();
+ xinit();
+ trapinit();
+ mmuinit();
+ plan9iniinit();
+ hwintrinit();
+ clockinit();
+ timerinit();
+ console();
+ quotefmtinstall();
+ printinit();
+ cpuidprint();
+ print("\nPlan 9 from Bell Labs\n");
+ procinit0();
+ initseg();
+ timersinit();
+ links();
+ chandevreset();
+ pageinit();
+ swapinit();
+ sharedseginit();
+ fpsave(&initfp);
+ initfp.fpscr = 0;
+ userinit();
+ schedinit();
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(name, plan9ini[i].name) == 0)
+ return plan9ini[i].val;
+ return nil;
+}
+
+static void
+plan9iniinit(void)
+{
+ long i;
+ int c;
+ char *cp, line[MAXCONF], *p, *q;
+
+ /*
+ * parse configuration args from dos file plan9.ini
+ */
+
+ cp = plan9inistr;
+ for(i = 0; i < MAXCONF; i++){
+ /*
+ * Strip out '\r', change '\t' -> ' ', test for 0xff which is end of file
+ */
+ p = line;
+ for(q = cp; c = (uchar)*q; q++){
+ if(c == '\r')
+ continue;
+ if(c == '\t')
+ c = ' ';
+ if(c == 0xff || c == '\n')
+ break;
+ *p++ = c;
+ }
+ *p = 0;
+ if (*line == 0)
+ break;
+ if(*line != '#' && (cp = strchr(line, '='))){
+ *cp++ = '\0';
+ kstrdup(&plan9ini[nconf].name, line);
+ kstrdup(&plan9ini[nconf].val, cp);
+ nconf++;
+ }
+ if (c == 0xff)
+ break;
+
+ cp = q + 1;
+ }
+}
+
+void
+init0(void)
+{
+// char **p, *q, name[KNAMELEN];
+ int i;
+ 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(i = 0; i < nconf; i++){
+ if(plan9ini[i].name[0] != '*')
+ ksetenv(plan9ini[i].name, plan9ini[i].val, 0);
+ ksetenv(plan9ini[i].name, plan9ini[i].val, 1);
+ }
+ poperror();
+ }
+ kproc("alarm", alarmkproc, 0);
+ kproc("mmusweep", mmusweep, 0);
+ touser((void*)(USTKTOP-sizeof(Tos)));
+}
+
+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;
+
+ /*
+ * 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);
+}
+
+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);
+
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+void
+procrestore(Proc *p)
+{
+ uvlong t;
+
+ if(p->kp)
+ return;
+ cycles(&t);
+ p->pcycles -= t;
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ uvlong t;
+
+ cycles(&t);
+ p->pcycles += t;
+ if(p->fpstate == FPactive){
+ if(p->state != Moribund)
+ fpsave(&up->fpsave);
+ p->fpstate = FPinactive;
+ }
+}
+
+void
+confinit(void)
+{
+ char *p;
+ int userpcnt;
+ ulong pa, kpages;
+ /* passed in from ROM monitor: */
+
+ if(p = getconf("*kernelpercent"))
+ userpcnt = 100 - strtol(p, 0, 0);
+ else
+ userpcnt = 0;
+
+ pa = PGROUND(PADDR(end));
+
+ /* Blast Board specific */
+ conf.mem[0].npage = (MEM1SIZE - pa)/BY2PG;
+ conf.mem[0].base = pa;
+
+ conf.mem[1].npage = MEM2SIZE/BY2PG;
+ conf.mem[1].base = MEM2BASE;
+
+ conf.npage = conf.mem[0].npage + conf.mem[1].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;
+}