| plan 9 kernel history: overview | file list | diff list |
1993/0330/pc/main.c (diff list | history)
| pc/main.c on 1991/0702 | ||
| 1991/0702 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1991/0706 | #include "mem.h" | |
| 1991/0702 | #include "dat.h" #include "fns.h" | |
| 1991/0706 | #include "io.h" | |
| 1991/0716 | #include "ureg.h" #include "init.h" | |
| 1992/0918 | #include <ctype.h> | |
| 1991/0629 | ||
| 1992/0904 | ||
| 1992/0903 | uchar *sp; /* stack pointer for /boot */ | |
| 1992/0923 | extern PCArch nsx20, generic, ncr3170; PCArch *arch; PCArch *knownarch[] = { &nsx20, &ncr3170, &generic, }; | |
| 1993/0330 | /* where b.com leaves configuration info */ #define BOOTARGS ((char*)(KZERO|1024)) #define BOOTARGSLEN 1024 #define MAXCONF 32 char *confname[MAXCONF]; char *confval[MAXCONF]; int nconf; | |
| 1991/0716 | void | |
| 1991/0702 | main(void) | |
| 1991/0625 | { | |
| 1991/1210 | ident(); | |
| 1992/0902 | i8042a20(); /* enable address lines 20 and up */ | |
| 1991/0711 | machinit(); | |
| 1991/1113 | active.exiting = 0; active.machs = 1; | |
| 1991/0711 | confinit(); | |
| 1992/0625 | xinit(); | |
| 1991/0703 | screeninit(); | |
| 1991/0716 | printinit(); | |
| 1991/0711 | mmuinit(); | |
| 1992/0625 | pageinit(); | |
| 1991/0718 | trapinit(); | |
| 1991/0906 | mathinit(); | |
| 1991/0718 | clockinit(); faultinit(); | |
| 1992/0409 | kbdinit(); | |
| 1991/0716 | procinit0(); initseg(); chandevreset(); streaminit(); swapinit(); userinit(); schedinit(); | |
| 1991/0712 | } | |
| 1991/0706 | ||
| 1992/0902 | /* | |
| 1992/0903 | * This tries to capture architecture dependencies since things * like power management/reseting/mouse are outside the hardware * model. | |
| 1992/0902 | */ | |
| 1991/0716 | void | |
| 1991/1210 | ident(void) { char *id = (char*)(ROMBIOS + 0xFF40); | |
| 1992/0923 | PCArch **p; | |
| 1991/1210 | ||
| 1992/0923 | for(p = knownarch; *p != &generic; p++) if(strncmp((*p)->id, id, strlen((*p)->id)) == 0) | |
| 1992/0918 | break; | |
| 1992/0923 | arch = *p; | |
| 1991/1210 | } void | |
| 1991/0716 | machinit(void) | |
| 1991/0712 | { | |
| 1991/0716 | int n; | |
| 1991/0712 | ||
| 1991/0716 | n = m->machno; memset(m, 0, sizeof(Mach)); m->machno = n; m->mmask = 1<<m->machno; | |
| 1991/0625 | } | |
| 1991/0719 | ulong garbage; | |
| 1991/0718 | ||
| 1991/0716 | void init0(void) | |
| 1991/0712 | { | |
| 1993/0330 | int i; | |
| 1992/0918 | char tstr[32]; | |
| 1991/0716 | u->nerrlab = 0; m->proc = u->p; u->p->state = Running; u->p->mach = m; | |
| 1991/0712 | ||
| 1991/0720 | spllo(); | |
| 1991/0716 | /* * These are o.k. because rootinit is null. * Then early kproc's will have a root and dot. */ u->slash = (*devtab[0].attach)(0); u->dot = clone(u->slash, 0); | |
| 1991/0712 | ||
| 1992/0516 | kproc("alarm", alarmkproc, 0); | |
| 1991/0716 | chandevinit(); | |
| 1991/0926 | if(!waserror()){ | |
| 1993/0330 | for(i = 0; i < nconf; i++) ksetenv(confname[i], confval[i]); | |
| 1992/0923 | strcpy(tstr, arch->id); | |
| 1992/0918 | strcat(tstr, " %s"); ksetterm(tstr); | |
| 1991/0927 | ksetenv("cputype", "386"); | |
| 1991/0926 | poperror(); } | |
| 1992/0323 | touser(sp); | |
| 1991/0712 | } | |
| 1991/0629 | void | |
| 1991/0716 | userinit(void) | |
| 1991/0711 | { | |
| 1991/0716 | Proc *p; Segment *s; User *up; KMap *k; | |
| 1992/0323 | Page *pg; | |
| 1991/0905 | ||
| 1991/0716 | p = newproc(); p->pgrp = newpgrp(); | |
| 1992/0625 | p->egrp = smalloc(sizeof(Egrp)); p->egrp->ref = 1; p->fgrp = smalloc(sizeof(Fgrp)); p->fgrp->ref = 1; | |
| 1991/1112 | p->procmode = 0640; | |
| 1991/0716 | strcpy(p->text, "*init*"); | |
| 1991/1109 | strcpy(p->user, eve); | |
| 1991/0716 | p->fpstate = FPinit; | |
| 1991/0906 | fpoff(); | |
| 1991/0716 | /* * Kernel Stack | |
| 1991/0717 | * | |
| 1991/0719 | * N.B. The -12 for the stack pointer is important. * 4 bytes for gotolabel's return PC | |
| 1991/0716 | */ p->sched.pc = (ulong)init0; | |
| 1991/0720 | p->sched.sp = USERADDR + BY2PG - 4; | |
| 1991/0716 | p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); /* * User */ k = kmap(p->upage); up = (User*)VA(k); up->p = p; kunmap(k); /* * User Stack */ s = newseg(SG_STACK, USTKTOP-BY2PG, 1); p->seg[SSEG] = s; | |
| 1992/0323 | pg = newpage(1, 0, USTKTOP-BY2PG); segpage(s, pg); k = kmap(pg); bootargs(VA(k)); kunmap(k); | |
| 1991/0716 | /* * Text */ s = newseg(SG_TEXT, UTZERO, 1); p->seg[TSEG] = s; segpage(s, newpage(1, 0, UTZERO)); k = kmap(s->map[0]->pages[0]); memmove((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); ready(p); | |
| 1992/0323 | } uchar * pusharg(char *p) { int n; n = strlen(p)+1; sp -= n; memmove(sp, p, n); return sp; } void bootargs(ulong base) { int i, ac; uchar *av[32]; uchar **lsp; | |
| 1992/0903 | char *cp = BOOTLINE; char buf[64]; | |
| 1992/0323 | sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD; ac = 0; av[ac++] = pusharg("/386/9safari"); av[ac++] = pusharg("-p"); | |
| 1992/0903 | cp[64] = 0; if(strncmp(cp, "fd!", 3) == 0){ sprint(buf, "local!#f/fd%ddisk", atoi(cp+3)); av[ac++] = pusharg(buf); } else if(strncmp(cp, "hd!", 3) == 0){ | |
| 1993/0114 | sprint(buf, "local!#h/hd%ddisk", atoi(cp+3)); | |
| 1992/0903 | av[ac++] = pusharg(buf); } | |
| 1992/0323 | /* 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; sp += (USTKTOP - BY2PG) - base - sizeof(ulong); | |
| 1991/0711 | } | |
| 1991/0716 | Conf conf; | |
| 1991/0711 | void confinit(void) { long x, i, j, *l; | |
| 1992/1002 | int pcnt; | |
| 1992/0715 | ulong ktop; | |
| 1993/0330 | char *cp; char *line[MAXCONF]; | |
| 1991/0711 | /* | |
| 1991/0823 | * the first 640k is the standard useful memory | |
| 1992/1113 | * the next 128K is the display, I/O mem, and BIOS | |
| 1992/0429 | * the last 256k belongs to the roms and other devices | |
| 1991/0711 | */ | |
| 1991/0823 | conf.npage0 = 640/4; conf.base0 = 0; /* * size the non-standard memory */ | |
| 1991/0711 | x = 0x12345678; | |
| 1992/1019 | for(i=2; i<17; i++){ | |
| 1991/0711 | /* * write the word */ | |
| 1992/0625 | l = (long*)(KZERO|(i*MB)); | |
| 1992/1019 | l--; | |
| 1991/0711 | *l = x; /* * take care of wraps */ | |
| 1992/1019 | for(j = 1; j < i; j++){ | |
| 1992/0625 | l = (long*)(KZERO|(j*MB)); | |
| 1992/1019 | l--; *l = ~x; | |
| 1991/0711 | } /* * check */ | |
| 1992/0625 | l = (long*)(KZERO|(i*MB)); | |
| 1992/1019 | l--; | |
| 1991/0711 | if(*l != x) break; | |
| 1993/0217 | memset((char*)(KZERO|((i-1)*MB)), 0, MB); | |
| 1991/0711 | x += 0x3141526; } | |
| 1992/1019 | i--; | |
| 1992/0625 | conf.base1 = 1*MB; | |
| 1992/1016 | conf.npage1 = (i*MB - conf.base1)/BY2PG; | |
| 1991/0711 | conf.npage = conf.npage0 + conf.npage1; | |
| 1992/1002 | ||
| 1992/1113 | conf.ldepth = 0; pcnt = (1<<conf.ldepth)-1; /* Calculate % of memory for page pool */ | |
| 1992/1014 | pcnt = 70 - (pcnt*10); conf.upages = (conf.npage*pcnt)/100; | |
| 1992/1016 | ktop = PGROUND((ulong)end); ktop = PADDR(ktop); conf.npage0 -= ktop/BY2PG; conf.base0 += ktop; | |
| 1991/0711 | ||
| 1992/0625 | conf.topofmem = i*MB; | |
| 1993/0330 | /* * parse configuration args from dos file p9rc */ cp = BOOTARGS; /* where b.com leaves it's config */ cp[BOOTARGSLEN-1] = 0; i = getfields(cp, line, MAXCONF, '\n'); for(j = 0; j < i; j++){ cp = strchr(line[j], '\r'); if(cp) *cp = 0; cp = strchr(line[j], '='); if(cp == 0) continue; *cp++ = 0; if(cp - line[j] >= NAMELEN+1) *(line[j]+NAMELEN-1) = 0; confname[nconf] = line[j]; confval[nconf] = cp; nconf++; } | |
| 1992/0625 | ||
| 1992/0807 | conf.monitor = 1; | |
| 1992/0103 | conf.nproc = 30 + i*5; | |
| 1991/0711 | conf.nswap = conf.nproc*80; conf.nimage = 50; conf.copymode = 0; /* copy on write */ | |
| 1992/0429 | conf.nfloppy = 2; | |
| 1992/1103 | conf.nhard = 2; | |
| 1991/0711 | } | |
| 1991/0913 | char *mathmsg[] = | |
| 1991/0906 | { | |
| 1991/0913 | "invalid", "denormalized", "div-by-zero", "overflow", "underflow", "precision", "stack", "error", }; | |
| 1991/0906 | /* | |
| 1991/0912 | * math coprocessor error */ void | |
| 1991/0913 | matherror(Ureg *ur) | |
| 1991/0912 | { | |
| 1991/0913 | ulong status; int i; char *msg; char note[ERRLEN]; /* * a write cycle to port 0xF0 clears the interrupt latch attached * to the error# line from the 387 */ outb(0xF0, 0xFF); | |
| 1992/0806 | /* * save floating point state to check out error */ fpenv(&u->fpsave); status = u->fpsave.status; msg = 0; | |
| 1991/0913 | for(i = 0; i < 8; i++) if((1<<i) & status){ msg = mathmsg[i]; | |
| 1992/0806 | sprint(note, "sys: fp: %s fppc=0x%lux", msg, u->fpsave.pc); postnote(u->p, 1, note, NDebug); | |
| 1991/0913 | break; } | |
| 1992/0806 | if(msg == 0){ sprint(note, "sys: fp: unknown fppc=0x%lux", u->fpsave.pc); postnote(u->p, 1, note, NDebug); } if(ur->pc & KZERO) panic("fp: status %lux fppc=0x%lux pc=0x%lux", status, u->fpsave.pc, ur->pc); | |
| 1991/0912 | } /* | |
| 1991/0906 | * math coprocessor emulation fault */ void mathemu(Ureg *ur) { | |
| 1992/0711 | USED(ur); | |
| 1991/0906 | switch(u->p->fpstate){ case FPinit: fpinit(); u->p->fpstate = FPactive; break; case FPinactive: fprestore(&u->fpsave); u->p->fpstate = FPactive; break; case FPactive: | |
| 1992/0805 | panic("math emu", 0); | |
| 1991/0906 | break; } } /* * math coprocessor segment overrun */ void mathover(Ureg *ur) { | |
| 1992/0711 | USED(ur); | |
| 1992/0805 | print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, u->p->pid); pexit("math overrun", 0); | |
| 1991/0906 | } void mathinit(void) { | |
| 1991/0913 | setvec(Matherr1vec, matherror); setvec(Matherr2vec, matherror); | |
| 1991/0906 | setvec(Mathemuvec, mathemu); setvec(Mathovervec, mathover); } /* | |
| 1991/0716 | * set up floating point for a new process */ | |
| 1991/0703 | void | |
| 1991/0716 | procsetup(Proc *p) | |
| 1991/0703 | { | |
| 1991/0716 | p->fpstate = FPinit; | |
| 1991/0906 | fpoff(); | |
| 1991/0705 | } | |
| 1991/0712 | /* | |
| 1991/0906 | * Save the mach dependent part of the process state. | |
| 1991/0712 | */ | |
| 1991/0705 | void | |
| 1992/0122 | procsave(Proc *p) | |
| 1991/0705 | { | |
| 1992/0805 | if(p->fpstate == FPactive){ if(p->state == Moribund) fpoff(); else fpsave(&u->fpsave); p->fpstate = FPinactive; | |
| 1991/0906 | } | |
| 1991/0712 | } /* | |
| 1991/0716 | * Restore what procsave() saves | |
| 1991/0712 | */ | |
| 1991/0716 | void | |
| 1992/0122 | procrestore(Proc *p) | |
| 1991/0712 | { | |
| 1992/0711 | USED(p); | |
| 1991/0712 | } | |
| 1991/0906 | /* | |
| 1991/1210 | * the following functions all are slightly different from * PC to PC. | |
| 1991/0803 | */ /* | |
| 1991/1210 | * reset the i387 chip | |
| 1991/0803 | */ void | |
| 1992/0812 | exit(int ispanic) | |
| 1991/0803 | { u = 0; print("exiting\n"); | |
| 1992/0812 | if(ispanic) for(;;); | |
| 1992/0903 | ||
| 1992/0923 | (*arch->reset)(); | |
| 1991/0803 | } /* | |
| 1991/1210 | * set cpu speed * 0 == low speed * 1 == high speed | |
| 1991/0803 | */ | |
| 1991/1210 | int cpuspeed(int speed) | |
| 1991/0803 | { | |
| 1992/0923 | if(arch->cpuspeed) return (*arch->cpuspeed)(speed); else | |
| 1991/1210 | return 0; | |
| 1991/0803 | } /* | |
| 1991/1210 | * f == frequency (Hz) * d == duration (ms) | |
| 1991/0803 | */ | |
| 1991/1210 | void buzz(int f, int d) | |
| 1991/0803 | { | |
| 1992/0923 | if(arch->buzz) (*arch->buzz)(f, d); | |
| 1991/0803 | } /* | |
| 1991/1210 | * each bit in val stands for a light | |
| 1991/0803 | */ | |
| 1991/1210 | void lights(int val) | |
| 1991/0803 | { | |
| 1992/0923 | if(arch->lights) (*arch->lights)(val); | |
| 1991/0803 | } /* | |
| 1991/0913 | * power to serial port | |
| 1991/1210 | * onoff == 1 means on * onoff == 0 means off | |
| 1991/0803 | */ int serial(int onoff) { | |
| 1992/0923 | if(arch->serialpower) return (*arch->serialpower)(onoff); else | |
| 1991/1210 | return 0; | |
| 1991/0803 | } | |
| 1991/1001 | /* * power to modem | |
| 1991/1210 | * onoff == 1 means on * onoff == 0 means off | |
| 1991/1001 | */ int modem(int onoff) { | |
| 1992/0923 | if(arch->modempower) return (*arch->modempower)(onoff); else | |
| 1991/1210 | return 0; | |
| 1991/0803 | } | |