| plan 9 kernel history: overview | file list | diff list |
1991/0710/power/main.c (diff list | history)
| power/main.c on 1990/0227 | ||
| 1990/0227 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "init.h" | |
| 1990/0424 | /* | |
| 1991/0425 | * software tlb simulation */ Softtlb stlb[4][STLBSIZE]; /* | |
| 1990/0424 | * args passed by boot process */ int _argc; char **_argv; char **_env; | |
| 1990/0504 | /* * arguments passed to initcode */ | |
| 1990/0427 | char argbuf[512]; int argsize; | |
| 1990/0424 | ||
| 1990/0504 | /* * environment passed to any kernel started by this kernel */ char envbuf[64]; char *env[2]; /* * configuration file read by boot program */ char confbuf[4*1024]; /* * system name */ char sysname[64]; | |
| 1990/0826 | /* | |
| 1990/0907 | * IO board type | |
| 1990/0826 | */ int ioid; | |
| 1990/1228 | ||
| 1990/11211 | char user[NAMELEN] = "bootes"; | |
| 1990/0227 | void main(void) { | |
| 1990/0801 | machinit(); | |
| 1990/0227 | active.exiting = 0; active.machs = 1; confinit(); | |
| 1990/0504 | arginit(); | |
| 1990/0227 | lockinit(); printinit(); | |
| 1991/0607 | duartspecial(0, &printq, &kbdq, 9600); | |
| 1990/0227 | tlbinit(); vecinit(); procinit0(); | |
| 1991/0705 | initseg(); grpinit(); | |
| 1990/0227 | chaninit(); clockinit(); alarminit(); | |
| 1990/0826 | ioboardinit(); | |
| 1990/0227 | chandevreset(); streaminit(); | |
| 1991/0705 | swapinit(); | |
| 1990/0227 | pageinit(); userinit(); launchinit(); schedinit(); } void machinit(void) { int n; | |
| 1990/0801 | icflush(0, 64*1024); | |
| 1990/0227 | n = m->machno; memset(m, 0, sizeof(Mach)); m->machno = n; | |
| 1991/0425 | m->stb = &stlb[n][0]; | |
| 1991/0607 | duartinit(); | |
| 1990/0227 | } void tlbinit(void) { int i; for(i=0; i<NTLB; i++) puttlbx(i, KZERO | PTEPID(i), 0); } void vecinit(void) { ulong *p, *q; int size; p = (ulong*)EXCEPTION; q = (ulong*)vector80; for(size=0; size<4; size++) *p++ = *q++; p = (ulong*)UTLBMISS; | |
| 1991/0425 | q = (ulong*)vector0; | |
| 1991/0426 | for(size=0; size<0x80/sizeof(*q); size++) | |
| 1990/0227 | *p++ = *q++; } /* | |
| 1990/11161 | * reset the vme bus */ void vmereset(void) { long i; int noforce; if(ioid >= IO3R1) noforce = 1; else noforce = 0; MODEREG->resetforce = (1<<1) | noforce; for(i=0; i<1000000; i++) ; MODEREG->resetforce = noforce; } /* | |
| 1990/0227 | * We have to program both the IO2 board to generate interrupts * and the SBCC on CPU 0 to accept them. */ void | |
| 1990/0826 | ioboardinit(void) | |
| 1990/0227 | { long i; | |
| 1990/0912 | int maxlevel; | |
| 1990/1228 | ushort *sp; | |
| 1990/0826 | ioid = *IOID; | |
| 1990/11161 | if(ioid >= IO3R1) | |
| 1991/0212 | maxlevel = 8; | |
| 1990/11161 | else | |
| 1990/0912 | maxlevel = 8; | |
| 1990/0911 | ||
| 1990/11161 | vmereset(); | |
| 1990/0227 | MODEREG->masterslave = (SLAVE<<4) | MASTER; /* * all VME interrupts to the error routine */ for(i=0; i<256; i++) setvmevec(i, novme); /* | |
| 1990/0907 | * tell IO2 to sent all interrupts to CPU 0's SBCC | |
| 1990/0227 | */ | |
| 1990/0912 | for(i=0; i<maxlevel; i++) | |
| 1990/0227 | INTVECREG->i[i].vec = 0<<8; /* * Tell CPU 0's SBCC to map all interrupts from the IO2 to MIPS level 5 * | |
| 1990/0825 | * 0x01 level 0 * 0x02 level 1 * 0x04 level 2 * 0x08 level 4 * 0x10 level 5 | |
| 1990/0227 | */ SBCCREG->flevel = 0x10; /* * Tell CPU 0's SBCC to enable all interrupts from the IO2. * * The SBCC 16 bit registers are read/written as ulong, but only * bits 23-16 and 7-0 are meaningful. */ | |
| 1990/0907 | SBCCREG->fintenable |= 0xff; /* allow all interrupts on the IO2 */ | |
| 1990/0227 | SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */ /* | |
| 1991/0212 | * Enable all interrupts on the IO2. If IO3, run in compatibility mode. | |
| 1990/0227 | */ | |
| 1991/0212 | *IO2SETMASK = 0xff000000; | |
| 1990/1228 | } | |
| 1990/0227 | void launchinit(void) { int i; for(i=1; i<conf.nmach; i++) launch(i); for(i=0; i<1000000; i++) if(active.machs == (1<<conf.nmach) - 1){ print("all launched\n"); return; } print("launch: active = %x\n", active.machs); } void init0(void) { | |
| 1990/0424 | int i; | |
| 1990/0427 | ulong *sp; | |
| 1990/0424 | ||
| 1990/0227 | m->proc = u->p; u->p->state = Running; u->p->mach = m; spllo(); | |
| 1990/0427 | ||
| 1991/0315 | /* * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. */ | |
| 1990/0227 | u->slash = (*devtab[0].attach)(0); u->dot = clone(u->slash, 0); | |
| 1991/0315 | chandevinit(); | |
| 1990/0227 | ||
| 1990/0427 | sp = (ulong*)(USTKTOP - argsize); | |
| 1991/0705 | kickpager(); | |
| 1990/0427 | touser(sp); | |
| 1990/0227 | } FPsave initfp; void userinit(void) { Proc *p; | |
| 1991/0705 | Segment *s; | |
| 1990/0227 | User *up; | |
| 1990/0617 | KMap *k; | |
| 1990/0427 | int i; char **av; | |
| 1991/0705 | Page *pg; | |
| 1990/0227 | p = newproc(); p->pgrp = newpgrp(); | |
| 1991/0705 | p->egrp = newegrp(); p->fgrp = newfgrp(); | |
| 1990/0227 | strcpy(p->text, "*init*"); strcpy(p->pgrp->user, "bootes"); savefpregs(&initfp); p->fpstate = FPinit; /* * Kernel Stack */ p->sched.pc = (ulong)init0; | |
| 1991/0710 | p->sched.sp = USERADDR+BY2PG-24; /* BUG */ | |
| 1990/0227 | p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF)); /* * User */ | |
| 1990/0617 | k = kmap(p->upage); up = (User*)VA(k); | |
| 1990/0227 | up->p = p; | |
| 1991/0314 | up->fpsave.fpstatus = initfp.fpstatus; | |
| 1990/0617 | kunmap(k); | |
| 1990/0227 | /* | |
| 1990/0427 | * User Stack, pass input arguments to boot process | |
| 1990/0227 | */ | |
| 1991/0705 | s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG); p->seg[SSEG] = s; pg = newpage(1, 0, USTKTOP-BY2PG); segpage(s, pg); memmove((ulong*)(pg->pa|KZERO|(BY2PG-argsize)), | |
| 1990/0427 | argbuf + sizeof(argbuf) - argsize, argsize); | |
| 1991/0705 | av = (char **)(pg->pa|KZERO|(BY2PG-argsize)); | |
| 1990/0427 | for(i = 0; i < _argc; i++) av[i] += (char *)USTKTOP - (argbuf + sizeof(argbuf)); | |
| 1990/0227 | /* * Text */ | |
| 1991/0705 | s = newseg(SG_TEXT, UTZERO, 1); p->seg[TSEG] = s; segpage(s, newpage(1, 0, UTZERO)); k = kmap(s->map[0]->pages[0]); | |
| 1991/0318 | memmove((ulong*)VA(k), initcode, sizeof initcode); | |
| 1990/0617 | kunmap(k); | |
| 1990/0227 | ready(p); } void lights(int v) { *LED = ~v; } typedef struct Beef Beef; struct Beef { long deadbeef; long sum; long cpuid; long virid; long erno; void (*launch)(void); void (*rend)(void); long junk1[4]; long isize; long dsize; long nonbss; long junk2[18]; }; void launch(int n) { Beef *p; | |
| 1990/0912 | long i, s; ulong *ptr; | |
| 1990/0227 | p = (Beef*) 0xb0000500 + n; p->launch = newstart; | |
| 1990/0912 | p->sum = 0; s = 0; ptr = (ulong*)p; for (i = 0; i < sizeof(Beef)/sizeof(ulong); i++) s += *ptr++; p->sum = -(s+1); | |
| 1990/0227 | for(i=0; i<3000000; i++) if(p->launch == 0) break; } void online(void) { machinit(); lock(&active); active.machs |= 1<<m->machno; unlock(&active); tlbinit(); clockinit(); schedinit(); } void exit(void) { int i; u = 0; lock(&active); active.machs &= ~(1<<m->machno); active.exiting = 1; unlock(&active); spllo(); print("cpu %d exiting\n", m->machno); | |
| 1991/0705 | while(active.machs || consactive()) | |
| 1990/0227 | for(i=0; i<1000; i++) ; splhi(); for(i=0; i<2000000; i++) ; | |
| 1991/0708 | duartenable0(); | |
| 1990/0227 | firmware(); } | |
| 1990/0504 | typedef struct Conftab { char *sym; ulong *x; } Conftab; #include "conf.h" | |
| 1990/0227 | Conf conf; | |
| 1990/0504 | ulong confeval(char *exp) { char *op; Conftab *ct; /* crunch leading white */ while(*exp==' ' || *exp=='\t') exp++; op = strchr(exp, '+'); if(op != 0){ *op++ = 0; return confeval(exp) + confeval(op); } op = strchr(exp, '*'); if(op != 0){ *op++ = 0; return confeval(exp) * confeval(op); } if(*exp >= '0' && *exp <= '9') return strtoul(exp, 0, 0); /* crunch trailing white */ op = strchr(exp, ' '); if(op) *op = 0; op = strchr(exp, '\t'); if(op) *op = 0; /* lookup in symbol table */ for(ct = conftab; ct->sym; ct++) if(strcmp(exp, ct->sym) == 0) return *(ct->x); return 0; } /* * each line of the configuration is of the form `param = expression'. */ | |
| 1990/0227 | void | |
| 1990/0504 | confset(char *sym) | |
| 1990/0227 | { | |
| 1990/0504 | char *val, *p; Conftab *ct; ulong x; | |
| 1990/0227 | ||
| 1990/0504 | /* * parse line */ | |
| 1990/0424 | ||
| 1990/0504 | /* comment */ if(p = strchr(sym, '#')) *p = 0; | |
| 1990/0227 | ||
| 1990/0504 | /* skip white */ for(p = sym; *p==' ' || *p=='\t'; p++) ; sym = p; /* skip sym */ for(; *p && *p!=' ' && *p!='\t' && *p!='='; p++) ; if(*p) *p++ = 0; /* skip white */ for(; *p==' ' || *p=='\t' || *p=='='; p++) ; val = p; /* * lookup value */ for(ct = conftab; ct->sym; ct++) if(strcmp(sym, ct->sym) == 0){ *(ct->x) = confeval(val); return; } if(strcmp(sym, "sysname")==0){ p = strchr(val, ' '); if(p) *p = 0; strcpy(sysname, val); } } /* * read the ascii configuration left by the boot kernel */ void confread(void) { char *line; char *end; /* * process configuration file */ line = confbuf; while(end = strchr(line, '\n')){ *end = 0; confset(line); line = end+1; } } void confprint(void) { Conftab *ct; /* * lookup value */ for(ct = conftab; ct->sym; ct++) print("%s == %d\n", ct->sym, *ct->x); } void confinit(void) { long x, i, j, *l; /* * copy configuration down from high memory */ strcpy(confbuf, (char *)(0x80000000 + 4*1024*1024 - 4*1024)); /* * size memory */ | |
| 1990/0227 | x = 0x12345678; | |
| 1990/0322 | for(i=4; i<128; i+=4){ | |
| 1990/0227 | l = (long*)(KSEG1|(i*1024L*1024L)); *l = x; wbflush(); *(ulong*)KSEG1 = *(ulong*)KSEG1; /* clear latches */ if(*l != x) break; x += 0x3141526; } | |
| 1990/0614 | conf.npage0 = i*1024/4; | |
| 1990/1211 | conf.base0 = 0; | |
| 1990/0614 | conf.npage = conf.npage0; | |
| 1990/1211 | conf.maxialloc = (128*1024*1024-256*1024-BY2PG); | |
| 1990/0504 | /* | |
| 1990/0907 | * clear MP bus error caused by sizing memory */ i = *SBEADDR; | |
| 1990/1214 | USED(i); | |
| 1990/0907 | /* | |
| 1990/0504 | * set minimal default values */ | |
| 1990/1127 | conf.nmach = 1; | |
| 1990/1202 | conf.nproc = 32; conf.npgrp = conf.nproc / 4; conf.npgenv = 4 * conf.npgrp; conf.nenv = 4 * conf.nproc; | |
| 1990/0911 | conf.nenvchar = 20 * conf.nenv; | |
| 1990/1202 | conf.nmtab = conf.nproc; | |
| 1991/0705 | conf.nseg = 4 * conf.nproc; conf.npagetab = conf.nseg*3; conf.nswap = 20000; conf.nimage = 200; | |
| 1990/1202 | conf.nchan = 20 * conf.nproc; conf.nmntdev = conf.nproc; conf.nmntbuf = conf.nproc; conf.nmnthdr = conf.nproc; conf.nstream = 2 * conf.nproc; conf.nalarm = 500; conf.nmount = 500; conf.nsrv = 3; conf.nnoifc = 1; conf.nnoconv = 32; conf.nurp = 25; | |
| 1990/11151 | conf.nqueue = 5 * conf.nstream; | |
| 1990/0911 | conf.nblock = 10 * conf.nstream; | |
| 1991/0424 | conf.ipif = 8; conf.ip = 64; conf.arp = 32; conf.frag = 32; | |
| 1990/0430 | ||
| 1990/0504 | confread(); | |
| 1991/0125 | conf.npipe = conf.nstream/2; /* must be after confread */ | |
| 1990/0504 | if(conf.nmach > MAXMACH) panic("confinit"); | |
| 1991/0705 | conf.copymode = 1; /* copy on reference */ conf.cntrlp = 1; | |
| 1990/0504 | } /* * 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. */ #define SYSENV "netaddr=" void arginit(void) { int i, n; int nbytes; int ssize; char *p; char **argv; char *charp; | |
| 1990/0430 | /* | |
| 1990/0504 | * get the system name from the environment | |
| 1990/0430 | */ | |
| 1990/0504 | if(*sysname == 0){ for(argv = _env; *argv; argv++){ if(strncmp(*argv, SYSENV, sizeof(SYSENV)-1)==0){ strcpy(sysname, (*argv) + sizeof(SYSENV)-1); break; } } } strcpy(envbuf, SYSENV); strcat(envbuf, sysname); env[0] = envbuf; env[1] = 0; /* * trim arguments to make them fit in the buffer (argv[0] is sysname) */ nbytes = 0; _argv[0] = sysname; for(i = 0; i < _argc; i++){ n = strlen(_argv[i]) + 1; ssize = BY2WD*(i+2) + ((nbytes+n+(BY2WD-1)) & ~(BY2WD-1)); if(ssize > sizeof(argbuf)) break; nbytes += n; } _argc = i; ssize = BY2WD*(i+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); /* * copy arguments into the buffer */ argv = (char**)(argbuf + sizeof(argbuf) - ssize); charp = (char*)(argbuf + sizeof(argbuf) - nbytes); for(i=0; i<_argc; i++){ argv[i] = charp; n = strlen(_argv[i]) + 1; | |
| 1991/0318 | memmove(charp, _argv[i], n); | |
| 1990/0504 | charp += n; } _argv = argv; argsize = ssize; | |
| 1990/1229 | } /* | |
| 1990/1231 | * setup the IO2 lance, io buffers are in lance memory | |
| 1990/1229 | */ void | |
| 1990/1231 | lanceIO2setup(Lance *lp) | |
| 1990/1229 | { | |
| 1990/1231 | ushort *sp; /* * reset lance and set parity on its memory */ MODEREG->promenet &= ~1; MODEREG->promenet |= 1; for(sp = LANCERAM; sp < LANCEEND; sp += 1) *sp = 0; lp->sep = 1; lp->lanceram = LANCERAM; lp->lm = (Lancemem*)0; /* * Allocate space in lance memory for the io buffers. * Start at 4k to avoid the initialization block and * descriptor rings. */ lp->lrp = (Etherpkt*)(4*1024); lp->ltp = lp->lrp + lp->nrrb; lp->rp = (Etherpkt*)(((ulong)LANCERAM) + (ulong)lp->lrp); lp->tp = lp->rp + lp->nrrb; | |
| 1990/1229 | } /* | |
| 1990/1231 | * setup the IO3 lance, io buffers are in host memory mapped to * lance address space | |
| 1990/1229 | */ void | |
| 1990/1231 | lanceIO3setup(Lance *lp) | |
| 1990/1229 | { | |
| 1990/1231 | ulong x, y; int index; ushort *sp; int len; /* * reset lance and set parity on its memory */ MODEREG->promenet |= 1; MODEREG->promenet &= ~1; for(sp = LANCE3RAM; sp < LANCE3END; sp += 2) *sp = 0; lp->sep = 4; lp->lanceram = LANCE3RAM; lp->lm = (Lancemem*)0x800000; /* * allocate some host memory for buffers and map it into lance * space */ len = (lp->nrrb + lp->ntrb)*sizeof(Etherpkt); lp->rp = (Etherpkt*)ialloc(len , 1); lp->tp = lp->rp + lp->nrrb; x = (ulong)lp->rp; lp->lrp = (Etherpkt*)(x & 0xFFF); lp->ltp = lp->lrp + lp->nrrb; index = LANCEINDEX; for(y = x+len; x < y; x += 0x1000){ *WRITEMAP = (index<<16) | (x>>12)&0xFFFF; index++; } | |
| 1990/1229 | } /* | |
| 1990/1231 | * set up the lance | |
| 1990/1229 | */ void | |
| 1990/1231 | lancesetup(Lance *lp) | |
| 1990/1229 | { | |
| 1990/1231 | lp->rap = LANCERAP; lp->rdp = LANCERDP; lp->ea[0] = LANCEID[20]>>8; lp->ea[1] = LANCEID[16]>>8; lp->ea[2] = LANCEID[12]>>8; lp->ea[3] = LANCEID[8]>>8; lp->ea[4] = LANCEID[4]>>8; lp->ea[5] = LANCEID[0]>>8; lp->lognrrb = 7; lp->logntrb = 7; lp->nrrb = 1<<lp->lognrrb; lp->ntrb = 1<<lp->logntrb; | |
| 1991/0109 | lp->busctl = BSWP; | |
| 1990/1231 | if(ioid >= IO3R1) lanceIO3setup(lp); else lanceIO2setup(lp); | |
| 1990/1229 | } void lanceparity(void) { print("lance DRAM parity error\n"); MODEREG->promenet &= ~4; MODEREG->promenet |= 4; | |
| 1990/0227 | } | |
| 1991/0607 | /* * for the sake of a single devcons.c */ void buzz(int f, int d) { } | |
| 1991/0705 | ||
| 1991/0607 | int mouseputc(IOQ *q, int c) { return 0; } | |