]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/mtx/main.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / 9 / mtx / main.c
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        "init.h"
8 #include        "pool.h"
9
10 Conf    conf;
11 FPsave  initfp;
12
13 void
14 main(void)
15 {
16         memset(edata, 0, (ulong)end-(ulong)edata);
17         conf.nmach = 1;
18         machinit();
19         ioinit();
20         i8250console();
21         quotefmtinstall();
22         print("\nPlan 9\n");
23         confinit();
24         xinit();
25         raveninit();
26         trapinit();
27         printinit();
28         cpuidprint();
29         mmuinit();
30         hwintrinit();
31         clockinit();
32         kbdinit();
33         procinit0();
34         initseg();
35         timersinit();
36         links();
37         chandevreset();
38         pageinit();
39         swapinit();
40         fpsave(&initfp);
41         initfp.fpscr = 0;
42         userinit();
43         schedinit();
44 }
45
46 void
47 machinit(void)
48 {
49         memset(m, 0, sizeof(Mach));
50         m->cputype = getpvr()>>16;
51
52         /*
53          * For polled uart output at boot, need
54          * a default delay constant. 100000 should
55          * be enough for a while. Cpuidentify will
56          * calculate the real value later.
57          */
58         m->loopconst = 100000;
59
60         /* turn on caches */
61         puthid0(gethid0() | BIT(16) | BIT(17));
62
63         active.machs = 1;
64         active.exiting = 0;
65 }
66
67 void
68 cpuidprint(void)
69 {
70         char *id;
71
72         id = "unknown PowerPC";
73         switch(m->cputype) {
74         case 9:
75                 id = "PowerPC 604e";
76                 break;
77         }
78         print("cpu0: %s\n", id);
79 }
80
81 static struct
82 {
83         char    *name;
84         char *val;
85 }
86 plan9ini[] =
87 {
88         { "console", "0" },
89         { "ether0", "type=2114x" },
90 };
91
92 char*
93 getconf(char *name)
94 {
95         int i;
96
97         for(i = 0; i < nelem(plan9ini); i++)
98                 if(cistrcmp(name, plan9ini[i].name) == 0)
99                         return plan9ini[i].val;
100         return nil;
101 }
102
103 void
104 init0(void)
105 {
106 //      char **p, *q, name[KNAMELEN];
107 //      int n;
108         char buf[2*KNAMELEN];
109
110         up->nerrlab = 0;
111
112         spllo();
113
114         /*
115          * These are o.k. because rootinit is null.
116          * Then early kproc's will have a root and dot.
117          */
118         up->slash = namec("#/", Atodir, 0, 0);
119         pathclose(up->slash->path);
120         up->slash->path = newpath("/");
121         up->dot = cclone(up->slash);
122
123         chandevinit();
124
125         if(!waserror()){
126                 snprint(buf, sizeof(buf), "power %s mtx", conffile);
127                 ksetenv("terminal", buf, 0);
128                 ksetenv("cputype", "power", 0);
129                 if(cpuserver)
130                         ksetenv("service", "cpu", 0);
131                 else
132                         ksetenv("service", "terminal", 0);
133                 
134 /*
135                 for(p = confenv; *p; p++) {
136                         q = strchr(p[0], '=');
137                         if(q == 0)
138                                 continue;
139                         n = q-p[0];
140                         if(n >= KNAMELEN)
141                                 n = KNAMELEN-1;
142                         memmove(name, p[0], n);
143                         name[n] = 0;
144                         if(name[0] != '*')
145                                 ksetenv(name, q+1, 0);
146                         ksetenv(name, q+1, 1);
147                 }
148 */
149                 poperror();
150         }
151         kproc("alarm", alarmkproc, 0);
152         kproc("mmusweep", mmusweep, 0);
153         touser((void*)(USTKTOP-8));
154 }
155
156 void
157 userinit(void)
158 {
159         Proc *p;
160         Segment *s;
161         KMap *k;
162         Page *pg;
163
164         p = newproc();
165         p->pgrp = newpgrp();
166         p->egrp = smalloc(sizeof(Egrp));
167         p->egrp->ref = 1;
168         p->fgrp = dupfgrp(nil);
169         p->rgrp = newrgrp();
170         p->procmode = 0640;
171
172         kstrdup(&eve, "");
173         kstrdup(&p->text, "*init*");
174         kstrdup(&p->user, eve);
175
176         p->fpstate = FPinit;
177
178         /*
179          * Kernel Stack
180          *
181          * N.B. The -12 for the stack pointer is important.
182          *      4 bytes for gotolabel's return PC
183          */
184         p->sched.pc = (ulong)init0;
185         p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
186
187         /*
188          * User Stack
189          */
190         s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
191         p->seg[SSEG] = s;
192         pg = newpage(1, 0, USTKTOP-BY2PG);
193         segpage(s, pg);
194
195         /*
196          * Text
197          */
198         s = newseg(SG_TEXT, UTZERO, 1);
199         s->flushme++;
200         p->seg[TSEG] = s;
201         pg = newpage(1, 0, UTZERO);
202         memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
203         segpage(s, pg);
204         k = kmap(s->map[0]->pages[0]);
205         memmove((ulong*)VA(k), initcode, sizeof initcode);
206         kunmap(k);
207
208         ready(p);
209 }
210
211 /* still to do */
212 void
213 reboot(void*, void*, ulong)
214 {
215         exit(0);
216 }
217
218 void
219 exit(int ispanic)
220 {
221         int ms, once;
222
223         lock(&active);
224         if(ispanic)
225                 active.ispanic = ispanic;
226         else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
227                 active.ispanic = 0;
228         once = active.machs & (1<<m->machno);
229         active.machs &= ~(1<<m->machno);
230         active.exiting = 1;
231         unlock(&active);
232
233         if(once)
234                 print("cpu%d: exiting\n", m->machno);
235         spllo();
236         for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
237                 delay(TK2MS(2));
238                 if(active.machs == 0 && consactive() == 0)
239                         break;
240         }
241
242         if(active.ispanic && m->machno == 0){
243                 if(cpuserver)
244                         delay(10000);
245                 else if(conf.monitor)
246                         for(;;);
247         }
248         else
249                 delay(1000);
250
251         watchreset();
252 }
253
254 /*
255  *  set up floating point for a new process
256  */
257 void
258 procsetup(Proc *p)
259 {
260         p->fpstate = FPinit;
261 }
262
263 /*
264  *  Save the mach dependent part of the process state.
265  */
266 void
267 procsave(Proc *p)
268 {
269         if(p->fpstate == FPactive){
270                 if(p->state != Moribund)
271                         fpsave(&up->fpsave);
272                 p->fpstate = FPinactive;
273         }
274 }
275
276 void
277 confinit(void)
278 {
279         char *p;
280         int userpcnt;
281         ulong pa, kpages;
282         extern ulong memsize;   /* passed in from ROM monitor */
283
284         if(p = getconf("*kernelpercent"))
285                 userpcnt = 100 - strtol(p, 0, 0);
286         else
287                 userpcnt = 0;
288
289         pa = PGROUND(PADDR(end));
290
291         conf.mem[0].npage = memsize/BY2PG;
292         conf.mem[0].base = pa;
293         conf.npage = conf.mem[0].npage;
294
295         conf.nmach = 1;
296         conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
297         if(cpuserver)
298                 conf.nproc *= 3;
299         if(conf.nproc > 2000)
300                 conf.nproc = 2000;
301         conf.nimage = 200;
302         conf.nswap = conf.nproc*80;
303         conf.nswppo = 4096;
304         conf.copymode = 0;                      /* copy on write */
305
306         if(cpuserver) {
307                 if(userpcnt < 10)
308                         userpcnt = 70;
309                 kpages = conf.npage - (conf.npage*userpcnt)/100;
310
311                 /*
312                  * Hack for the big boys. Only good while physmem < 4GB.
313                  * Give the kernel a max. of 16MB + enough to allocate the
314                  * page pool.
315                  * This is an overestimate as conf.upages < conf.npages.
316                  * The patch of nimage is a band-aid, scanning the whole
317                  * page list in imagereclaim just takes too long.
318                  */
319                 if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
320                         kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
321                         conf.nimage = 2000;
322                         kpages += (conf.nproc*KSTACK)/BY2PG;
323                 }
324         } else {
325                 if(userpcnt < 10) {
326                         if(conf.npage*BY2PG < 16*MB)
327                                 userpcnt = 40;
328                         else
329                                 userpcnt = 60;
330                 }
331                 kpages = conf.npage - (conf.npage*userpcnt)/100;
332
333                 /*
334                  * Make sure terminals with low memory get at least
335                  * 4MB on the first Image chunk allocation.
336                  */
337                 if(conf.npage*BY2PG < 16*MB)
338                         imagmem->minarena = 4*1024*1024;
339         }
340         conf.upages = conf.npage - kpages;
341         conf.ialloc = (kpages/2)*BY2PG;
342
343         /*
344          * Guess how much is taken by the large permanent
345          * datastructures. Mntcache and Mntrpc are not accounted for
346          * (probably ~300KB).
347          */
348         kpages *= BY2PG;
349         kpages -= conf.upages*sizeof(Page)
350                 + conf.nproc*sizeof(Proc)
351                 + conf.nimage*sizeof(Image)
352                 + conf.nswap
353                 + conf.nswppo*sizeof(Page);
354         mainmem->maxsize = kpages;
355         if(!cpuserver){
356                 /*
357                  * give terminals lots of image memory, too; the dynamic
358                  * allocation will balance the load properly, hopefully.
359                  * be careful with 32-bit overflow.
360                  */
361                 imagmem->maxsize = kpages;
362         }
363
364 //      conf.monitor = 1;       /* BUG */
365 }
366
367 static int
368 getcfields(char* lp, char** fields, int n, char* sep)
369 {
370         int i;
371
372         for(i = 0; lp && *lp && i < n; i++){
373                 while(*lp && strchr(sep, *lp) != 0)
374                         *lp++ = 0;
375                 if(*lp == 0)
376                         break;
377                 fields[i] = lp;
378                 while(*lp && strchr(sep, *lp) == 0){
379                         if(*lp == '\\' && *(lp+1) == '\n')
380                                 *lp++ = ' ';
381                         lp++;
382                 }
383         }
384
385         return i;
386 }
387
388 int
389 isaconfig(char *class, int ctlrno, ISAConf *isa)
390 {
391         int i;
392         char cc[KNAMELEN], *p;
393
394         sprint(cc, "%s%d", class, ctlrno);
395
396         p = getconf(cc);
397         if(p == 0)
398                 return 0;
399         isa->nopt = tokenize(p, isa->opt, NISAOPT);
400         for(i = 0; i < isa->nopt; i++){
401                 p = isa->opt[i];
402                 if(cistrncmp(p, "type=", 5) == 0)
403                         isa->type = p + 5;
404                 else if(cistrncmp(p, "port=", 5) == 0)
405                         isa->port = strtoul(p+5, &p, 0);
406                 else if(cistrncmp(p, "irq=", 4) == 0)
407                         isa->irq = strtoul(p+4, &p, 0);
408                 else if(cistrncmp(p, "dma=", 4) == 0)
409                         isa->dma = strtoul(p+4, &p, 0);
410                 else if(cistrncmp(p, "mem=", 4) == 0)
411                         isa->mem = strtoul(p+4, &p, 0);
412                 else if(cistrncmp(p, "size=", 5) == 0)
413                         isa->size = strtoul(p+5, &p, 0);
414                 else if(cistrncmp(p, "freq=", 5) == 0)
415                         isa->freq = strtoul(p+5, &p, 0);
416         }
417         return 1;
418 }
419
420 int
421 cistrcmp(char *a, char *b)
422 {
423         int ac, bc;
424
425         for(;;){
426                 ac = *a++;
427                 bc = *b++;
428         
429                 if(ac >= 'A' && ac <= 'Z')
430                         ac = 'a' + (ac - 'A');
431                 if(bc >= 'A' && bc <= 'Z')
432                         bc = 'a' + (bc - 'A');
433                 ac -= bc;
434                 if(ac)
435                         return ac;
436                 if(bc == 0)
437                         break;
438         }
439         return 0;
440 }
441
442 int
443 cistrncmp(char *a, char *b, int n)
444 {
445         unsigned ac, bc;
446
447         while(n > 0){
448                 ac = *a++;
449                 bc = *b++;
450                 n--;
451
452                 if(ac >= 'A' && ac <= 'Z')
453                         ac = 'a' + (ac - 'A');
454                 if(bc >= 'A' && bc <= 'Z')
455                         bc = 'a' + (bc - 'A');
456
457                 ac -= bc;
458                 if(ac)
459                         return ac;
460                 if(bc == 0)
461                         break;
462         }
463
464         return 0;
465 }