]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bitsy/main.c
merge
[plan9front.git] / sys / src / 9 / bitsy / 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        "ureg.h"
8 #include        "init.h"
9 #include        "pool.h"
10
11 Mach    *m;
12 Proc    *up;
13 Conf    conf;
14 int     noprint;
15
16 void
17 main(void)
18 {
19         mmuinvalidate();
20
21         /* zero out bss */
22         memset(edata, 0, end-edata);
23
24         /* point to Mach structure */
25         m = (Mach*)MACHADDR;
26         memset(m, 0, sizeof(Mach));
27         m->ticks = 1;
28
29         active.machs = 1;
30
31         rs232power(1);
32         quotefmtinstall();
33         iprint("\nPlan 9 bitsy kernel\n");
34         confinit();
35         xinit();
36         mmuinit();
37         machinit();
38         trapinit();
39         sa1110_uartsetup(1);
40         dmainit();
41         screeninit();
42         printinit();    /* from here on, print works, before this we need iprint */
43         clockinit();
44         procinit0();
45         initseg();
46         links();
47         chandevreset();
48         pageinit();
49         swapinit();
50         userinit();
51         powerinit();
52         schedinit();
53 }
54
55 /* need to do better */
56 void
57 reboot(void*, void*, ulong)
58 {
59         exit(0);
60 }
61
62
63 /*
64  *  exit kernel either on a panic or user request
65  */
66 void
67 exit(int ispanic)
68 {
69         void (*f)(void);
70
71         USED(ispanic);
72         delay(1000);
73
74         iprint("it's a wonderful day to die\n");
75         cacheflush();
76         mmuinvalidate();
77         mmudisable();
78         f = nil;
79         (*f)();
80 }
81
82 static uchar *sp;
83
84 /*
85  *  starting place for first process
86  */
87 void
88 init0(void)
89 {
90         up->nerrlab = 0;
91
92         spllo();
93
94         /*
95          * These are o.k. because rootinit is null.
96          * Then early kproc's will have a root and dot.
97          */
98         up->slash = namec("#/", Atodir, 0, 0);
99         pathclose(up->slash->path);
100         up->slash->path = newpath("/");
101         up->dot = cclone(up->slash);
102
103         chandevinit();
104
105         if(!waserror()){
106                 ksetenv("terminal", "bitsy", 0);
107                 ksetenv("cputype", "arm", 0);
108                 if(cpuserver)
109                         ksetenv("service", "cpu", 0);
110                 else
111                         ksetenv("service", "terminal", 0);
112                 poperror();
113         }
114         kproc("alarm", alarmkproc, 0);
115         kproc("power", powerkproc, 0);
116
117         touser(sp);
118 }
119
120 /*
121  *  pass boot arguments to /boot
122  */
123 static uchar *
124 pusharg(char *p)
125 {
126         int n;
127
128         n = strlen(p)+1;
129         sp -= n;
130         memmove(sp, p, n);
131         return sp;
132 }
133 static void
134 bootargs(ulong base)
135 {
136         int i, ac;
137         uchar *av[32];
138         uchar *bootpath;
139         uchar **lsp;
140
141         /*
142          *  the sizeof(Sargs) is to make the validaddr check in
143          *  trap.c's syscall() work even when we have less than the
144          *  max number of args.
145          */
146         sp = (uchar*)base + BY2PG - sizeof(Sargs);
147
148         bootpath = pusharg("/boot/boot");
149         ac = 0;
150         av[ac++] = pusharg("boot");
151
152         /* 4 byte word align stack */
153         sp = (uchar*)((ulong)sp & ~3);
154
155         /* build argc, argv on stack */
156         sp -= (ac+1)*sizeof(sp);
157         lsp = (uchar**)sp;
158         for(i = 0; i < ac; i++)
159                 *lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
160         *lsp = 0;
161
162         /* push argv onto stack */
163         sp -= BY2WD;
164         lsp = (uchar**)sp;
165         *lsp = sp + BY2WD + ((USTKTOP - BY2PG) - base);
166
167         /* push pointer to "/boot" */
168         sp -= BY2WD;
169         lsp = (uchar**)sp;
170         *lsp = bootpath + ((USTKTOP - BY2PG) - base);
171
172         /* leave space for where the initcode's caller's return PC would normally reside */
173         sp -= BY2WD;
174
175         /* relocate stack to user's virtual addresses */
176         sp += (USTKTOP - BY2PG) - base;
177 }
178
179 /*
180  *  create the first process
181  */
182 void
183 userinit(void)
184 {
185         Proc *p;
186         Segment *s;
187         KMap *k;
188         Page *pg;
189
190         /* no processes yet */
191         up = nil;
192
193         p = newproc();
194         p->pgrp = newpgrp();
195         p->egrp = smalloc(sizeof(Egrp));
196         p->egrp->ref = 1;
197         p->fgrp = dupfgrp(nil);
198         p->rgrp = newrgrp();
199         p->procmode = 0640;
200
201         kstrdup(&eve, "");
202         kstrdup(&p->text, "*init*");
203         kstrdup(&p->user, eve);
204
205         /*
206          * Kernel Stack
207          */
208         p->sched.pc = (ulong)init0;
209         p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
210
211         /*
212          * User Stack
213          */
214         s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
215         p->seg[SSEG] = s;
216         pg = newpage(1, 0, USTKTOP-BY2PG);
217         segpage(s, pg);
218         k = kmap(pg);
219         bootargs(VA(k));
220         kunmap(k);
221
222         /*
223          * Text
224          */
225         s = newseg(SG_TEXT, UTZERO, 1);
226         p->seg[TSEG] = s;
227         pg = newpage(1, 0, UTZERO);
228         memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
229         segpage(s, pg);
230         k = kmap(s->map[0]->pages[0]);
231         memmove((ulong*)VA(k), initcode, sizeof initcode);
232         kunmap(k);
233
234         ready(p);
235 }
236
237 /*
238  *  set mach dependent process state for a new process
239  */
240 void
241 procsetup(Proc *p)
242 {
243         p->fpstate = FPinit;
244 }
245
246 void
247 procfork(Proc*)
248 {
249 }
250
251 /*
252  *  Save the mach dependent part of the process state.
253  */
254 void
255 procsave(Proc *p)
256 {
257         USED(p);
258 }
259
260 /* place holder */
261 /*
262  *  dummy since rdb is not included 
263  */
264 void
265 rdb(void)
266 {
267 }
268
269 /*
270  *  probe the last location in a meg of memory, make sure it's not
271  *  reflected into something else we've already found.
272  */
273 int
274 probemem(ulong addr)
275 {
276         int i;
277         ulong *p;
278         ulong a;
279
280         addr += OneMeg - sizeof(ulong);
281         p = (ulong*)addr;
282         *p = addr;
283         for(i=0; i<nelem(conf.mem); i++){
284                 for(a = conf.mem[i].base+OneMeg-sizeof(ulong); a < conf.mem[i].limit; a += OneMeg){
285                         p = (ulong*)a;
286                         *p = 0;
287                 }
288         }
289         p = (ulong*)addr;
290         if(*p != addr)
291                 return -1;
292         return 0;
293 }
294
295 /*
296  *  we assume that the kernel is at the beginning of one of the
297  *  contiguous chunks of memory.
298  */
299 void
300 confinit(void)
301 {
302         int i, j;
303         ulong addr;
304         ulong ktop;
305
306         /* find first two contiguous sections of available memory */
307         addr = PHYSDRAM0;
308         for(i=0; i<nelem(conf.mem); i++){
309                 conf.mem[i].base = addr;
310                 conf.mem[i].limit = addr;
311         }
312         for(j=0; j<nelem(conf.mem); j++){
313                 conf.mem[j].base = addr;
314                 conf.mem[j].limit = addr;
315                 
316                 for(i = 0; i < 512; i++){
317                         if(probemem(addr) == 0)
318                                 break;
319                         addr += OneMeg;
320                 }
321                 for(; i < 512; i++){
322                         if(probemem(addr) < 0)
323                                 break;
324                         addr += OneMeg;
325                         conf.mem[j].limit = addr;
326                 }
327         }
328         
329         conf.npage = 0;
330         for(i=0; i<nelem(conf.mem); i++){
331                 /* take kernel out of allocatable space */
332                 ktop = PGROUND((ulong)end);
333                 if(ktop >= conf.mem[i].base && ktop <= conf.mem[i].limit)
334                         conf.mem[i].base = ktop;
335                 
336                 /* zero memory */
337                 memset((void*)conf.mem[i].base, 0, conf.mem[i].limit - conf.mem[i].base);
338
339                 conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
340                 conf.npage += conf.mem[i].npage;
341         }
342
343         if(conf.npage > 16*MB/BY2PG){
344                 conf.upages = (conf.npage*60)/100;
345                 imagmem->minarena = 4*1024*1024;
346         }else
347                 conf.upages = (conf.npage*40)/100;
348         conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
349
350         /* only one processor */
351         conf.nmach = 1;
352
353         /* set up other configuration parameters */
354         conf.nproc = 100;
355         conf.nswap = conf.npage*3;
356         conf.nswppo = 4096;
357         conf.nimage = 200;
358
359         conf.monitor = 1;
360
361         conf.copymode = 0;              /* copy on write */
362 }
363
364 GPIOregs *gpioregs;
365 ulong *egpioreg = (ulong*)EGPIOREGS;
366 PPCregs *ppcregs;
367 MemConfRegs *memconfregs;
368 PowerRegs *powerregs;
369 ResetRegs *resetregs;
370
371 /*
372  *  configure the machine
373  */
374 void
375 machinit(void)
376 {
377         /* set direction of SA1110 io pins and select alternate functions for some */
378         gpioregs = mapspecial(GPIOREGS, sizeof(GPIOregs));
379         gpioregs->direction = 
380                 GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
381                 |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
382                 |GPIO_CLK_SET0_o|GPIO_CLK_SET1_o
383                 |GPIO_L3_SDA_io|GPIO_L3_MODE_o|GPIO_L3_SCLK_o
384                 |GPIO_COM_RTS_o;
385         gpioregs->rising = 0;
386         gpioregs->falling = 0;
387         gpioregs->altfunc |= 
388                 GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
389                 |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
390                 |GPIO_SSP_CLK_i;
391
392         /* map in special H3650 io pins */
393         egpioreg = mapspecial(EGPIOREGS, sizeof(ulong));
394
395         /* map in peripheral pin controller (ssp will need it) */
396         ppcregs = mapspecial(PPCREGS, sizeof(PPCregs));
397
398         /* SA1110 power management */
399         powerregs = mapspecial(POWERREGS, sizeof(PowerRegs));
400
401         /* memory configuraton */
402         memconfregs = mapspecial(MEMCONFREGS, sizeof(MemConfRegs));
403
404         /* reset controller */
405         resetregs = mapspecial(RESETREGS, sizeof(ResetRegs));
406 }
407
408
409 /*
410  *  manage egpio bits
411  */
412 static ulong egpiosticky;
413
414 void
415 egpiobits(ulong bits, int on)
416 {
417         if(on)
418                 egpiosticky |= bits;
419         else
420                 egpiosticky &= ~bits;
421         *egpioreg = egpiosticky;
422 }
423
424 void
425 rs232power(int on)
426 {
427         egpiobits(EGPIO_rs232_power, on);
428         delay(50);
429 }
430
431 void
432 audioamppower(int on)
433 {
434         egpiobits(EGPIO_audio_power, on);
435         delay(50);
436 }
437
438 void
439 audioicpower(int on)
440 {
441         egpiobits(EGPIO_audio_ic_power, on);
442         delay(50);
443 }
444
445 void
446 irpower(int on)
447 {
448         egpiobits(EGPIO_ir_power, on);
449         delay(50);
450 }
451
452 void
453 lcdpower(int on)
454 {
455         egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on);
456         delay(50);
457 }
458
459 void
460 flashprogpower(int on)
461 {
462         egpiobits(EGPIO_prog_flash, on);
463 }
464
465 /* here on hardware reset */
466 void
467 resettrap(void)
468 {
469 }
470
471 /*
472  *  for drivers that used to run on x86's
473  */
474 void
475 outb(ulong a, uchar v)
476 {
477         *(uchar*)a = v;
478 }
479 void
480 outs(ulong a, ushort v)
481 {
482         *(ushort*)a = v;
483 }
484 void
485 outss(ulong a, void *p, int n)
486 {
487         ushort *sp = p;
488
489         while(n-- > 0)
490                 *(ushort*)a = *sp++;
491 }
492 void
493 outl(ulong a, ulong v)
494 {
495         *(ulong*)a = v;
496 }
497 uchar
498 inb(ulong a)
499 {
500         return *(uchar*)a;
501 }
502 ushort
503 ins(ulong a)
504 {
505         return *(ushort*)a;
506 }
507 void
508 inss(ulong a, void *p, int n)
509 {
510         ushort *sp = p;
511
512         while(n-- > 0)
513                 *sp++ = *(ushort*)a;
514 }
515 ulong
516 inl(ulong a)
517 {
518         return *(ulong*)a;
519 }
520
521 char*
522 getconf(char*)
523 {
524         return nil;
525 }
526
527 long
528 _xdec(long *p)
529 {
530         int s;
531         long v;
532
533         s = splhi();
534         v = --*p;
535         splx(s);
536         return v;
537 }
538
539 void
540 _xinc(long *p)
541 {
542         int s;
543
544         s = splhi();
545         ++*p;
546         splx(s);
547 }
548
549 int
550 cmpswap(long *addr, long old, long new)
551 {
552         int r, s;
553         
554         s = splhi();
555         if(r = (*addr==old))
556                 *addr = new;
557         splx(s);
558         return r;
559 }
560