123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- #include "all.h"
- #include "mem.h"
- #include "io.h"
- #include "ureg.h"
- /*
- * Where configuration info is left for the loaded programme.
- * This will turn into a structure as more is done by the boot loader
- * (e.g. why parse the .ini file twice?).
- * There are 1024 bytes available at CONFADDR.
- */
- #define BOOTLINE ((char*)CONFADDR)
- #define BOOTLINELEN 64
- #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
- #define BOOTARGSLEN (1024-BOOTLINELEN)
- #define MAXCONF 32
- #define KADDR(a) ((void*)((ulong)(a)|KZERO))
- char bootdisk[NAMELEN];
- char *confname[MAXCONF];
- char *confval[MAXCONF];
- int nconf;
- static int isoldbcom;
- 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;
- }
- static void
- options(void)
- {
- uchar *bda;
- long i, n;
- char *cp, *line[MAXCONF], *p, *q;
- if(strncmp(BOOTARGS, "ZORT 0\r\n", 8)){
- isoldbcom = 1;
- memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN);
- memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN);
- bda = KADDR(0x400);
- bda[0x13] = 639;
- bda[0x14] = 639>>8;
- }
- /*
- * parse configuration args from dos file plan9.ini
- */
- cp = BOOTARGS; /* where b.com leaves its config */
- cp[BOOTARGSLEN-1] = 0;
- /*
- * Strip out '\r', change '\t' -> ' '.
- */
- p = cp;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
- *p = 0;
- n = getcfields(cp, line, MAXCONF, "\n");
- for(i = 0; i < n; i++){
- if(*line[i] == '#')
- continue;
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- }
- /*
- * Vecinit is the first hook we have into configuring the machine,
- * so we do it all here. A pox on special fileserver code.
- * We do more in meminit below.
- */
- void
- vecinit(void)
- {
- options();
- }
- 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;
- }
- char*
- getconf(char *name)
- {
- int i;
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- return confval[i];
- return 0;
- }
- /* memory map */
- /* the file server kernel will only see MAXMEG megabytes of RAM at most. */
- #define MAXMEG 1024
- char mmap[MAXMEG+2];
- Mconf mconf;
- static void
- mconfinit(void)
- {
- long x, i, j;
- ulong ktop;
- Mbank *mbp;
- uchar *bda;
- /*
- * size memory above 1 meg. Kernel sits at 1 meg. We
- * only recognize MB size chunks.
- */
- memset(mmap, ' ', sizeof(mmap));
- x = 0x12345678;
- for(i = 1; i <= MAXMEG; i++){
- /*
- * write the first & last word in a megabyte of memory
- */
- *mapaddr(KZERO|(i*MB)) = x;
- *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x;
- /*
- * write the first and last word in all previous megs to
- * handle address wrap around
- */
- for(j = 1; j < i; j++){
- *mapaddr(KZERO|(j*MB)) = ~x;
- *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x;
- }
- /*
- * check for correct value
- */
- if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x)
- mmap[i] = 'x';
- x += 0x3141526;
- }
- /*
- * bank[0] goes from the end of the bootstrap structures to ~640k.
- * want to use this up first for ialloc because sparemem
- * will want a large contiguous chunk.
- */
- mbp = mconf.bank;
- mbp->base = PADDR(CPU0MACH+BY2PG);
- bda = (uchar*)(KZERO|0x400);
- mbp->limit = ((bda[0x14]<<8)|bda[0x13])*1024;
- mbp++;
- /*
- * bank[1] usually goes from the end of kernel bss to the end of memory
- */
- ktop = PGROUND((ulong)end);
- ktop = PADDR(ktop);
- mbp->base = ktop;
- for(i = 1; mmap[i] == 'x'; i++)
- ;
- mbp->limit = i*MB;
- mconf.topofmem = mbp->limit;
- mbp++;
- /*
- * Look for any other chunks of memory.
- */
- for(; i <= MAXMEG; i++){
- if(mmap[i] == 'x'){
- mbp->base = i*MB;
- for(j = i+1; mmap[j] == 'x'; j++)
- ;
- mbp->limit = j*MB;
- mconf.topofmem = j*MB;
- mbp++;
- if((mbp - mconf.bank) >= MAXBANK)
- break;
- }
- }
- mconf.nbank = mbp - mconf.bank;
- }
- ulong
- meminit(void)
- {
- conf.nmach = 1;
- mconfinit();
- mmuinit();
- trapinit();
- /*
- * This is not really right, but the port code assumes
- * a linear memory array and this is as close as we can
- * get to satisfying that.
- * Dancing around the 'port' code is all just an ugly hack
- * anyway.
- */
- return mconf.topofmem;
- }
- void
- userinit(void (*f)(void), void *arg, char *text)
- {
- User *p;
- p = newproc();
- /*
- * Kernel Stack.
- * The -4 is because the path sched()->gotolabel()->init0()->f()
- * uses a stack location without creating any local space.
- */
- p->sched.pc = (ulong)init0;
- p->sched.sp = (ulong)p->stack + sizeof(p->stack) - 4;
- p->start = f;
- p->text = text;
- p->arg = arg;
- dofilter(p->time+0, C0a, C0b, 1);
- dofilter(p->time+1, C1a, C1b, 1);
- dofilter(p->time+2, C2a, C2b, 1);
- ready(p);
- }
- static int useuart;
- static void (*intrputs)(char*, int);
- static int
- pcgetc(void)
- {
- int c;
- if(c = kbdgetc())
- return c;
- if(useuart)
- return uartgetc();
- }
- static void
- pcputc(int c)
- {
- if(predawn)
- cgaputc(c);
- if(useuart)
- uartputc(c);
- }
- static void
- pcputs(char* s, int n)
- {
- if(!predawn)
- cgaputs(s, n);
- if(intrputs)
- (*intrputs)(s, n);
- }
- void
- consinit(void (*puts)(char*, int))
- {
- char *p;
- int baud, port;
- kbdinit();
- consgetc = pcgetc;
- consputc = pcputc;
- consputs = pcputs;
- intrputs = puts;
- if((p = getconf("console")) == 0 || cistrcmp(p, "cga") == 0)
- return;
- port = strtoul(p, 0, 0);
- baud = 0;
- if(p = getconf("baud"))
- baud = strtoul(p, 0, 0);
- if(baud == 0)
- baud = 9600;
- uartspecial(port, kbdchar, conschar, baud);
- useuart = 1;
- }
- void
- consreset(void)
- {
- }
- void
- firmware(void)
- {
- char *p;
- /*
- * Always called splhi().
- */
- if((p = getconf("reset")) && cistrcmp(p, "manual") == 0){
- predawn = 1;
- print("\nHit Reset\n");
- for(;;);
- }
- pcireset();
- i8042reset();
- }
- int
- isaconfig(char *class, int ctlrno, ISAConf *isa)
- {
- char cc[NAMELEN], *p, *q, *r;
- int n;
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(cistrncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(cistrncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- 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);
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
- }
- void
- lockinit(void)
- {
- }
- void
- launchinit(void)
- {
- }
- void
- lights(int, int)
- {
- }
- /* in assembly language
- Float
- famd(Float a, int b, int c, int d)
- {
- return ((a+b) * c) / d;
- }
- ulong
- fdf(Float a, int b)
- {
- return a / b;
- }
- */
|