|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "io.h"
7: #include "ureg.h"
8: #include "init.h"
9: #include <ctype.h>
10:
11:
12: uchar *sp; /* stack pointer for /boot */
13:
14: extern PCArch nsx20, generic, ncr3170;
15:
16: PCArch *arch;
17: PCArch *knownarch[] =
18: {
19: &nsx20,
20: &ncr3170,
21: &generic,
22: };
23:
24: /* where b.com leaves configuration info */
25: #define BOOTARGS ((char*)(KZERO|1024))
26: #define BOOTARGSLEN 1024
27: #define MAXCONF 32
28:
29: char bootdisk[NAMELEN];
30: char *confname[MAXCONF];
31: char *confval[MAXCONF];
32: int nconf;
33:
34: /* memory map */
35: #define MAXMEG 64
36: char mmap[MAXMEG+2];
37:
38: void
39: main(void)
40: {
41: ident();
42: i8042a20(); /* enable address lines 20 and up */
43: machinit();
44: active.exiting = 0;
45: active.machs = 1;
46: confinit();
47: xinit();
48: dmainit();
49: screeninit();
50: printinit();
51: mmuinit();
52: pageinit();
53: trapinit();
54: mathinit();
55: clockinit();
56: printcpufreq();
57: faultinit();
58: kbdinit();
59: procinit0();
60: initseg();
61: streaminit();
62: chandevreset();
63: swapinit();
64: userinit();
65: schedinit();
66: }
67:
68: /*
69: * This tries to capture architecture dependencies since things
70: * like power management/reseting/mouse are outside the hardware
71: * model.
72: */
73: void
74: ident(void)
75: {
76: char *id = (char*)(ROMBIOS + 0xFF40);
77: PCArch **p;
78:
79: for(p = knownarch; *p != &generic; p++)
80: if(strncmp((*p)->id, id, strlen((*p)->id)) == 0)
81: break;
82: arch = *p;
83: }
84:
85: void
86: machinit(void)
87: {
88: int n;
89:
90: n = m->machno;
91: memset(m, 0, sizeof(Mach));
92: m->machno = n;
93: m->mmask = 1<<m->machno;
94: }
95:
96: ulong garbage;
97:
98: void
99: init0(void)
100: {
101: int i;
102: char tstr[32];
103:
104: u->nerrlab = 0;
105: m->proc = u->p;
106: u->p->state = Running;
107: u->p->mach = m;
108:
109: spllo();
110:
111: /*
112: * These are o.k. because rootinit is null.
113: * Then early kproc's will have a root and dot.
114: */
115: u->slash = (*devtab[0].attach)(0);
116: u->dot = clone(u->slash, 0);
117:
118: kproc("alarm", alarmkproc, 0);
119: chandevinit();
120:
121: if(!waserror()){
122: strcpy(tstr, arch->id);
123: strcat(tstr, " %s");
124: ksetterm(tstr);
125: ksetenv("cputype", "386");
126: for(i = 0; i < nconf; i++)
127: if(confname[i])
128: ksetenv(confname[i], confval[i]);
129: poperror();
130: }
131: touser(sp);
132: }
133:
134: void
135: userinit(void)
136: {
137: Proc *p;
138: Segment *s;
139: User *up;
140: KMap *k;
141: Page *pg;
142:
143: p = newproc();
144: p->pgrp = newpgrp();
145: p->egrp = smalloc(sizeof(Egrp));
146: p->egrp->ref = 1;
147: p->fgrp = smalloc(sizeof(Fgrp));
148: p->fgrp->ref = 1;
149: p->procmode = 0640;
150:
151: strcpy(p->text, "*init*");
152: strcpy(p->user, eve);
153: p->fpstate = FPinit;
154: fpoff();
155:
156: /*
157: * Kernel Stack
158: *
159: * N.B. The -12 for the stack pointer is important.
160: * 4 bytes for gotolabel's return PC
161: */
162: p->sched.pc = (ulong)init0;
163: p->sched.sp = USERADDR + BY2PG - 4;
164: p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
165:
166: /*
167: * User
168: */
169: k = kmap(p->upage);
170: up = (User*)VA(k);
171: up->p = p;
172: kunmap(k);
173:
174: /*
175: * User Stack
176: */
177: s = newseg(SG_STACK, USTKTOP-BY2PG, 1);
178: p->seg[SSEG] = s;
179: pg = newpage(1, 0, USTKTOP-BY2PG);
180: segpage(s, pg);
181: k = kmap(pg);
182: bootargs(VA(k));
183: kunmap(k);
184:
185: /*
186: * Text
187: */
188: s = newseg(SG_TEXT, UTZERO, 1);
189: p->seg[TSEG] = s;
190: segpage(s, newpage(1, 0, UTZERO));
191: k = kmap(s->map[0]->pages[0]);
192: memmove((ulong*)VA(k), initcode, sizeof initcode);
193: kunmap(k);
194:
195: ready(p);
196: }
197:
198: uchar *
199: pusharg(char *p)
200: {
201: int n;
202:
203: n = strlen(p)+1;
204: sp -= n;
205: memmove(sp, p, n);
206: return sp;
207: }
208:
209: void
210: bootargs(ulong base)
211: {
212: int i, ac;
213: uchar *av[32];
214: uchar **lsp;
215: char *cp = BOOTLINE;
216: char buf[64];
217:
218: sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD;
219:
220: ac = 0;
221: av[ac++] = pusharg("/386/9pc");
222: cp[64] = 0;
223: buf[0] = 0;
224:
225: /*
226: * decode the b.com bootline and convert to
227: * a disk device name to pass to the boot
228: */
229: if(strncmp(cp, "fd!", 3) == 0){
230: sprint(buf, "local!#f/fd%ddisk", atoi(cp+3));
231: av[ac++] = pusharg(buf);
232: } else if(strncmp(cp, "h!", 2) == 0){
233: sprint(buf, "local!#H/hd%dfs", atoi(cp+2));
234: av[ac++] = pusharg(buf);
235: } else if(strncmp(cp, "hd!", 3) == 0){
236: sprint(buf, "local!#H/hd%ddisk", atoi(cp+3));
237: av[ac++] = pusharg(buf);
238: } else if(strncmp(cp, "s!", 2) == 0){
239: sprint(buf, "local!#w%d/sd%dfs", atoi(cp+2), atoi(cp+2));
240: av[ac++] = pusharg(buf);
241: } else if(strncmp(cp, "sd!", 3) == 0){
242: sprint(buf, "local!#w%d/sd%ddisk", atoi(cp+3), atoi(cp+3));
243: av[ac++] = pusharg(buf);
244: } else if(getconf("bootdisk") == 0){
245: if(conf.nhard){
246: sprint(buf, "local!#H/hd0disk");
247: av[ac++] = pusharg(buf);
248: } else{
249: sprint(buf, "local!#w/sd0disk");
250: av[ac++] = pusharg(buf);
251: }
252: }
253: if(buf[0]){
254: cp = strchr(buf, '!');
255: if(cp){
256: strcpy(bootdisk, cp+1);
257: addconf("bootdisk", bootdisk);
258: }
259: }
260:
261: /* 4 byte word align stack */
262: sp = (uchar*)((ulong)sp & ~3);
263:
264: /* build argc, argv on stack */
265: sp -= (ac+1)*sizeof(sp);
266: lsp = (uchar**)sp;
267: for(i = 0; i < ac; i++)
268: *lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
269: *lsp = 0;
270: sp += (USTKTOP - BY2PG) - base - sizeof(ulong);
271: }
272:
273: Conf conf;
274:
275: void
276: addconf(char *name, char *val)
277: {
278: if(nconf >= MAXCONF)
279: return;
280: confname[nconf] = name;
281: confval[nconf] = val;
282: nconf++;
283: }
284:
285: char*
286: getconf(char *name)
287: {
288: int i;
289:
290: for(i = 0; i < nconf; i++)
291: if(strcmp(confname[i], name) == 0)
292: return confval[i];
293: return 0;
294: }
295:
296: /*
297: * look for unused address space in 0xC8000 to 1 meg
298: */
299: void
300: romscan(void)
301: {
302: uchar *p;
303:
304: p = (uchar*)(KZERO+0xC8000);
305: while(p < (uchar*)(KZERO+0xE0000)){
306: p[0] = 0x55;
307: p[1] = 0xAA;
308: p[2] = 4;
309: if(p[0] != 0x55 || p[1] != 0xAA){
310: putisa(PADDR(p), 2048);
311: p += 2048;
312: continue;
313: }
314: p += p[2]*512;
315: }
316:
317: p = (uchar*)(KZERO+0xE0000);
318: if(p[0] != 0x55 || p[1] != 0xAA)
319: putisa(PADDR(p), 64*1024);
320: }
321:
322:
323: void
324: confinit(void)
325: {
326: long x, i, j, n;
327: int pcnt;
328: ulong ktop;
329: char *cp;
330: char *line[MAXCONF];
331:
332: pcnt = 0;
333:
334: /*
335: * parse configuration args from dos file p9rc
336: */
337: cp = BOOTARGS; /* where b.com leaves plan9.ini */
338: cp[BOOTARGSLEN-1] = 0;
339: n = getfields(cp, line, MAXCONF, "\n");
340: for(j = 0; j < n; j++){
341: cp = strchr(line[j], '\r');
342: if(cp)
343: *cp = 0;
344: cp = strchr(line[j], '=');
345: if(cp == 0)
346: continue;
347: *cp++ = 0;
348: if(cp - line[j] >= NAMELEN+1)
349: *(line[j]+NAMELEN-1) = 0;
350: confname[nconf] = line[j];
351: confval[nconf] = cp;
352: if(strcmp(confname[nconf], "kernelpercent") == 0)
353: pcnt = 100 - atoi(confval[nconf]);
354: nconf++;
355: }
356: /*
357: * size memory above 1 meg. Kernel sits at 1 meg. We
358: * only recognize MB size chunks.
359: */
360: memset(mmap, ' ', sizeof(mmap));
361: x = 0x12345678;
362: for(i = 1; i <= MAXMEG; i++){
363: /*
364: * write the first & last word in a megabyte of memory
365: */
366: *mapaddr(KZERO|(i*MB)) = x;
367: *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x;
368:
369: /*
370: * write the first and last word in all previous megs to
371: * handle address wrap around
372: */
373: for(j = 1; j < i; j++){
374: *mapaddr(KZERO|(j*MB)) = ~x;
375: *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x;
376: }
377:
378: /*
379: * check for correct value
380: */
381: if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x){
382: mmap[i] = 'x';
383: /*
384: * zero memory to set ECC but skip over the kernel
385: */
386: if(i != 1)
387: for(j = 0; j < MB/BY2PG; j += BY2PG)
388: memset(mapaddr(KZERO|(i*MB+j)), 0, BY2PG);
389: }
390: x += 0x3141526;
391: }
392: /*
393: * bank0 usually goes from the end of kernel bss to the end of memory
394: */
395: ktop = PGROUND((ulong)end);
396: ktop = PADDR(ktop);
397: conf.base0 = ktop;
398: for(i = 1; mmap[i] == 'x'; i++)
399: ;
400: conf.npage0 = (i*MB - ktop)/BY2PG;
401: conf.topofmem = i*MB;
402:
403: /*
404: * bank1 usually goes from the end of BOOTARGS to 640k
405: */
406: conf.base1 = (ulong)(BOOTARGS+BOOTARGSLEN);
407: conf.base1 = PGROUND(conf.base1);
408: conf.base1 = PADDR(conf.base1);
409: conf.npage1 = (640*1024-conf.base1)/BY2PG;
410:
411: /*
412: * if there is a hole in memory (due to a shadow BIOS) make the
413: * memory after the hole be bank 1. The memory from 0 to 640k
414: * is lost.
415: */
416: for(; i <= MAXMEG; i++)
417: if(mmap[i] == 'x'){
418: conf.base1 = i*MB;
419: for(j = i+1; mmap[j] == 'x'; j++)
420: ;
421: conf.npage1 = (j - i)*MB/BY2PG;
422: conf.topofmem = j*MB;
423: break;
424: }
425:
426: /*
427: * add address space holes holes under 16 meg to available
428: * isa space.
429: */
430: romscan();
431: if(conf.topofmem < 16*MB)
432: putisa(conf.topofmem, 16*MB - conf.topofmem);
433:
434: conf.npage = conf.npage0 + conf.npage1;
435: conf.ldepth = 0;
436: if(pcnt < 10)
437: pcnt = 70;
438: conf.upages = (conf.npage*pcnt)/100;
439:
440: conf.nproc = 30 + ((conf.npage*BY2PG)/MB)*8;
441: conf.monitor = 1;
442: conf.nswap = conf.nproc*80;
443: conf.nimage = 50;
444: switch(x86()){
445: case 3:
446: conf.copymode = 1; /* copy on reference */
447: break;
448: default:
449: conf.copymode = 0; /* copy on write */
450: break;
451: }
452: conf.nfloppy = 2;
453: conf.nhard = 2;
454: conf.nmach = 1;
455: }
456:
457: char *mathmsg[] =
458: {
459: "invalid",
460: "denormalized",
461: "div-by-zero",
462: "overflow",
463: "underflow",
464: "precision",
465: "stack",
466: "error",
467: };
468:
469: /*
470: * math coprocessor error
471: */
472: void
473: matherror(Ureg *ur, void *a)
474: {
475: ulong status;
476: int i;
477: char *msg;
478: char note[ERRLEN];
479:
480: USED(a);
481:
482: /*
483: * a write cycle to port 0xF0 clears the interrupt latch attached
484: * to the error# line from the 387
485: */
486: outb(0xF0, 0xFF);
487:
488: /*
489: * save floating point state to check out error
490: */
491: fpenv(&u->fpsave);
492: status = u->fpsave.status;
493:
494: msg = 0;
495: for(i = 0; i < 8; i++)
496: if((1<<i) & status){
497: msg = mathmsg[i];
498: sprint(note, "sys: fp: %s fppc=0x%lux", msg, u->fpsave.pc);
499: postnote(u->p, 1, note, NDebug);
500: break;
501: }
502: if(msg == 0){
503: sprint(note, "sys: fp: unknown fppc=0x%lux", u->fpsave.pc);
504: postnote(u->p, 1, note, NDebug);
505: }
506: if(ur->pc & KZERO)
507: panic("fp: status %lux fppc=0x%lux pc=0x%lux", status,
508: u->fpsave.pc, ur->pc);
509: }
510:
511: /*
512: * math coprocessor emulation fault
513: */
514: void
515: mathemu(Ureg *ur, void *a)
516: {
517: USED(ur, a);
518:
519: switch(u->p->fpstate){
520: case FPinit:
521: fpinit();
522: u->p->fpstate = FPactive;
523: break;
524: case FPinactive:
525: fprestore(&u->fpsave);
526: u->p->fpstate = FPactive;
527: break;
528: case FPactive:
529: panic("math emu", 0);
530: break;
531: }
532: }
533:
534: /*
535: * math coprocessor segment overrun
536: */
537: void
538: mathover(Ureg *ur, void *a)
539: {
540: USED(ur, a);
541:
542: print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, u->p->pid);
543: pexit("math overrun", 0);
544: }
545:
546: void
547: mathinit(void)
548: {
549: setvec(Matherr1vec, matherror, 0);
550: setvec(Matherr2vec, matherror, 0);
551: setvec(Mathemuvec, mathemu, 0);
552: setvec(Mathovervec, mathover, 0);
553: }
554:
555: /*
556: * set up floating point for a new process
557: */
558: void
559: procsetup(Proc *p)
560: {
561: p->fpstate = FPinit;
562: fpoff();
563: }
564:
565: /*
566: * Save the mach dependent part of the process state.
567: */
568: void
569: procsave(Proc *p)
570: {
571: if(p->fpstate == FPactive){
572: if(p->state == Moribund)
573: fpoff();
574: else
575: fpsave(&u->fpsave);
576: p->fpstate = FPinactive;
577: }
578: }
579:
580: /*
581: * Restore what procsave() saves
582: */
583: void
584: procrestore(Proc *p)
585: {
586: USED(p);
587: }
588:
589:
590: /*
591: * the following functions all are slightly different from
592: * PC to PC.
593: */
594:
595: /*
596: * reset the i387 chip
597: */
598: void
599: exit(int ispanic)
600: {
601: u = 0;
602: wipekeys();
603: print("exiting\n");
604: if(ispanic){
605: if(cpuserver)
606: delay(10000);
607: else
608: for(;;);
609: }
610:
611: (*arch->reset)();
612: }
613:
614: /*
615: * set cpu speed
616: * 0 == low speed
617: * 1 == high speed
618: */
619: int
620: cpuspeed(int speed)
621: {
622: if(arch->cpuspeed)
623: return (*arch->cpuspeed)(speed);
624: else
625: return 0;
626: }
627:
628: /*
629: * f == frequency (Hz)
630: * d == duration (ms)
631: */
632: void
633: buzz(int f, int d)
634: {
635: if(arch->buzz)
636: (*arch->buzz)(f, d);
637: }
638:
639: /*
640: * each bit in val stands for a light
641: */
642: void
643: lights(int val)
644: {
645: if(arch->lights)
646: (*arch->lights)(val);
647: }
648:
649: /*
650: * power to serial port
651: * onoff == 1 means on
652: * onoff == 0 means off
653: */
654: int
655: serial(int onoff)
656: {
657: if(arch->serialpower)
658: return (*arch->serialpower)(onoff);
659: else
660: return 0;
661: }
662:
663: /*
664: * power to modem
665: * onoff == 1 means on
666: * onoff == 0 means off
667: */
668: int
669: modem(int onoff)
670: {
671: if(arch->modempower)
672: return (*arch->modempower)(onoff);
673: else
674: return 0;
675: }
676:
677: int
678: parseether(uchar *to, char *from)
679: {
680: char nip[4];
681: char *p;
682: int i;
683:
684: p = from;
685: while(*p == ' ')
686: ++p;
687: for(i = 0; i < 6; i++){
688: if(*p == 0)
689: return -1;
690: nip[0] = *p++;
691: if(*p == 0)
692: return -1;
693: nip[1] = *p++;
694: nip[2] = 0;
695: to[i] = strtoul(nip, 0, 16);
696: if(*p == ':')
697: p++;
698: }
699: return 0;
700: }
701:
702: int
703: isaconfig(char *class, int ctlrno, ISAConf *isa)
704: {
705: char cc[NAMELEN], *p, *q;
706: int n;
707:
708: sprint(cc, "%s%d", class, ctlrno);
709: for(n = 0; n < nconf; n++){
710: if(strncmp(confname[n], cc, NAMELEN))
711: continue;
712: p = confval[n];
713: while(*p){
714: while(*p == ' ' || *p == '\t')
715: p++;
716: if(*p == '\0')
717: break;
718: if(strncmp(p, "type=", 5) == 0){
719: p += 5;
720: for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
721: if(*p == '\0' || *p == ' ' || *p == '\t')
722: break;
723: *q = *p++;
724: }
725: *q = '\0';
726: }
727: else if(strncmp(p, "port=", 5) == 0)
728: isa->port = strtoul(p+5, &p, 0);
729: else if(strncmp(p, "irq=", 4) == 0)
730: isa->irq = strtoul(p+4, &p, 0);
731: else if(strncmp(p, "mem=", 4) == 0)
732: isa->mem = strtoul(p+4, &p, 0);
733: else if(strncmp(p, "size=", 5) == 0)
734: isa->size = strtoul(p+5, &p, 0);
735: else if(strncmp(p, "dma=", 4) == 0)
736: isa->dma = strtoul(p+4, &p, 0);
737: else if(strncmp(p, "ea=", 3) == 0){
738: if(parseether(isa->ea, p+3) == -1)
739: memset(isa->ea, 0, 6);
740: }
741: while(*p && *p != ' ' && *p != '\t')
742: p++;
743: }
744: return 1;
745: }
746: return 0;
747: }
748:
749: static void
750: pcfloppyintr(Ureg *ur, void *a)
751: {
752: USED(a);
753:
754: floppyintr(ur);
755: }
756:
757: void
758: floppysetup0(FController *fl)
759: {
760: USED(fl);
761: }
762:
763: void
764: floppysetup1(FController *fl)
765: {
766: uchar equip;
767:
768: /*
769: * read nvram for types of floppies 0 & 1
770: */
771: equip = nvramread(0x10);
772: if(conf.nfloppy > 0){
773: fl->d[0].dt = (equip >> 4) & 0xf;
774: floppysetdef(&fl->d[0]);
775: }
776: if(conf.nfloppy > 1){
777: fl->d[1].dt = equip & 0xf;
778: floppysetdef(&fl->d[1]);
779: }
780:
781: setvec(Floppyvec, pcfloppyintr, 0);
782: }
783:
784: /*
785: * eject disk ( unknown on safari )
786: */
787: void
788: floppyeject(FDrive *dp)
789: {
790: floppyon(dp);
791: dp->vers++;
792: floppyoff(dp);
793: }
794:
795: int
796: floppyexec(char *a, long b, int c)
797: {
798: USED(a, b, c);
799: return b;
800: }
801:
802: int
803: cistrcmp(char *a, char *b)
804: {
805: int ac, bc;
806:
807: for(;;){
808: ac = *a++;
809: bc = *b++;
810:
811: if(ac >= 'A' && ac <= 'Z')
812: ac = 'a' + (ac - 'A');
813: if(bc >= 'A' && bc <= 'Z')
814: bc = 'a' + (bc - 'A');
815: ac -= bc;
816: if(ac)
817: return ac;
818: if(bc == 0)
819: break;
820: }
821: return 0;
822: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.