]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/sgi/main.c
usbehci: catch interrupt in tsleep
[plan9front.git] / sys / src / 9 / sgi / 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 #include        "../ip/ip.h"
10 #include        <tos.h>
11 #include        <../port/error.h>
12
13 enum {
14         /* space for syscall args, return PC, top-of-stack struct */
15         Stkheadroom     = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
16 };
17
18 static uchar *sp;               /* XXX - must go - user stack of init proc */
19 static FPsave initfp;
20
21 /*
22  * software tlb simulation
23  */
24 static Softtlb stlb[MAXMACH][STLBSIZE];
25
26 Conf    conf;
27
28 char*
29 getconf(char *name)
30 {
31         return (char*)arcs(0x78, name);
32 }
33
34 static void
35 fmtinit(void)
36 {
37         printinit();
38         quotefmtinstall();
39         /* ipreset installs these when chandevreset runs */
40         fmtinstall('i', eipfmt);
41         fmtinstall('I', eipfmt);
42         fmtinstall('E', eipfmt);
43         fmtinstall('V', eipfmt);
44         fmtinstall('M', eipfmt);
45 }
46
47 static int
48 ckpagemask(ulong mask, ulong size)
49 {
50         int s;
51         ulong pm;
52
53         s = splhi();
54         setpagemask(mask);
55         pm = getpagemask();
56         splx(s);
57         if(pm != mask){
58                 iprint("page size %ldK not supported on this cpu; "
59                         "mask %#lux read back as %#lux\n", size/1024, mask, pm);
60                 return -1;
61         }
62         return 0;
63 }
64
65 void
66 addmem(uintptr base, uintptr top)
67 {
68         uintptr s, e;
69         ulong *m;
70         int i;
71
72         if(base >= top)
73                 return;
74
75         /* exclude kernel */
76         s = 0;
77         e = PADDR(PGROUND((uintptr)end));
78         if(s < top && e > base){
79                 if(s > base)
80                         addmem(base, s);
81                 if(e < top)
82                         addmem(e, top);
83                 return;
84         }
85
86         /* exclude reserved firmware memory regions */
87         m = nil;
88         while((m = (ulong*)arcs(0x48, m)) != nil){
89                 s = m[1]<<12;
90                 e = s + (m[2]<<12);
91                 switch(m[0]){
92                 case 2: /* FreeMemory */
93                 case 3: /* BadMemory */
94                         continue;
95                 }
96                 if(s < top && e > base){
97                         if(s > base)
98                                 addmem(base, s);
99                         if(e < top)
100                                 addmem(e, top);
101                         return;
102                 }
103         }
104         for(i=0; i<nelem(conf.mem); i++){
105                 if(conf.mem[i].npage == 0){
106                         conf.mem[i].base = base;
107                         conf.mem[i].npage = (top - base)/BY2PG;
108
109                         conf.npage += conf.mem[i].npage;
110                         return;
111                 }
112         }
113         print("conf.mem[] too small\n");
114 }
115
116 /* 
117  * get memory configuration word for a bank
118  */
119 ulong
120 bank_conf(int bank)
121 {
122         switch(bank){
123         case 0:
124                 return *(ulong *)(KSEG1|MEMCFG0) >> 16;
125         case 1:
126                 return *(ulong *)(KSEG1|MEMCFG0) & 0xffff;
127         case 2:
128                 return *(ulong *)(KSEG1|MEMCFG1) >> 16;
129         case 3:
130                 return *(ulong *)(KSEG1|MEMCFG1) & 0xffff;
131         }
132         return 0;
133 }
134
135 void
136 meminit(void)
137 {
138         uintptr base, size, top;
139         ulong mconf;
140         int i;
141
142         /*
143          *  divide memory twixt user pages and kernel.
144          */
145         conf.npage = 0;
146         for(i=0; i<4; i++){
147                 mconf = bank_conf(i);
148                 if(!(mconf & 0x2000))
149                         continue;
150                 base = (mconf & 0xff) << 22;
151                 size = ((mconf & 0x1f00) + 0x0100) << 14;
152                 top = base + size;
153                 addmem(base, top);
154         }
155 }
156
157 static int
158 havegfx(void)
159 {
160         char *s = getconf("ConsoleOut");
161         return s != nil && strstr(s, "video()") != nil;
162 }
163
164 void
165 main(void)
166 {
167         savefpregs(&initfp);
168
169         arcsconsinit();
170
171         meminit();
172         confinit();
173         machinit();                     /* calls clockinit */
174         active.exiting = 0;
175         active.machs[0] = 1;
176         print("\nPlan 9\n");
177
178         kmapinit();
179         xinit();
180         timersinit();
181         fmtinit();
182
183         if(havegfx()){
184                 conf.monitor = 1;
185                 screeninit();
186         }
187
188         ckpagemask(PGSZ, BY2PG);
189         tlbinit();
190         pageinit();
191         procinit0();
192         initseg();
193         links();
194         chandevreset();
195         userinit();
196         schedinit();
197         panic("schedinit returned");
198 }
199
200 /*
201  *  initialize a processor's mach structure.  each processor does this
202  *  for itself.
203  */
204 void
205 machinit(void)
206 {
207         extern void gevector(void);     /* l.s */
208         extern void utlbmiss(void);
209         extern void vector0(void);
210         extern void vector180(void);
211
212         void **sbp = (void*)SPBADDR;
213
214         m->stb = stlb[m->machno];
215
216         /* install exception handlers */
217         sbp[0x18/4] = utlbmiss;
218         sbp[0x14/4] = gevector;
219
220         /* we could install our own vectors directly, but we'll try to play nice */
221         if(0){
222                 memmove((void*)(KSEG0+0x0), (void*)vector0, 0x80);
223                 memmove((void*)(KSEG0+0x180), (void*)vector180, 0x80);
224                 icflush((void*)(KSEG0+0x0), 0x80);
225                 icflush((void*)(KSEG0+0x180), 0x80);
226         }
227
228         /* Ensure CU1 is off */
229         clrfpintr();
230         clockinit();
231 }
232
233 void
234 init0(void)
235 {
236         char buf[128];
237
238         up->nerrlab = 0;
239
240         spllo();
241
242         /*
243          * These are o.k. because rootinit is null.
244          * Then early kproc's will have a root and dot.
245          */
246         up->slash = namec("#/", Atodir, 0, 0);
247         pathclose(up->slash->path);
248         up->slash->path = newpath("/");
249         up->dot = cclone(up->slash);
250
251         chandevinit();
252
253         if(!waserror()){
254                 ksetenv("cputype", "mips", 0);
255                 snprint(buf, sizeof buf, "mips %s", conffile);
256                 ksetenv("terminal", buf, 0);
257                 if(cpuserver)
258                         ksetenv("service", "cpu", 0);
259                 else
260                         ksetenv("service", "terminal", 0);
261
262                 ksetenv("bootargs", "tcp", 0);
263                 ksetenv("console", "0", 0);
264
265                 /* no usb */
266                 ksetenv("usbwait", "0", 0);
267                 ksetenv("nousbrc", "1", 0);
268
269                 poperror();
270         }
271
272         /* process input for arcs console */
273         if(!conf.keyboard)
274                 kproc("arcs", arcsproc, 0);
275
276         kproc("alarm", alarmkproc, 0);
277         touser(sp);
278 }
279
280 static uchar *
281 pusharg(char *p)
282 {
283         int n;
284         
285         n = strlen(p) + 1;
286         sp -= n;
287         memmove(sp, p, n);
288         return sp;
289 }
290
291 static void
292 bootargs(uintptr base)
293 {       int i, ac;
294         uchar *av[32];
295         uchar **lsp;
296         
297         sp = (uchar *) base + BY2PG - sizeof(Tos);
298         
299         ac = 0;
300         av[ac++] = pusharg("boot");
301         sp = (uchar *) ((ulong) sp & ~7);
302         sp -= ROUND((ac + 1) * sizeof(sp), 8) + 4;
303         lsp = (uchar **) sp;
304         for(i = 0; i < ac; i++)
305                 lsp[i] = av[i] + ((USTKTOP - BY2PG) - (ulong) base);
306         lsp[i] = 0;
307         sp += (USTKTOP - BY2PG) - (ulong) base;
308 }
309
310 void
311 userinit(void)
312 {
313         Proc *p;
314         KMap *k;
315         Page *pg;
316         Segment *s;
317
318         p = newproc();
319         p->pgrp = newpgrp();
320         p->egrp = smalloc(sizeof(Egrp));
321         p->egrp->ref = 1;
322         p->fgrp = dupfgrp(nil);
323         p->rgrp = newrgrp();
324         p->procmode = 0640;
325
326         kstrdup(&eve, "");
327         kstrdup(&p->text, "*init*");
328         kstrdup(&p->user, eve);
329
330         procsetup(p);
331
332         /*
333          * Kernel Stack
334          */
335         p->sched.pc = (ulong)init0;
336         p->sched.sp = (ulong)p->kstack+KSTACK-Stkheadroom;
337         p->sched.sp = STACKALIGN(p->sched.sp);
338
339         /*
340          * User Stack
341          *
342          * Technically, newpage can't be called here because it
343          * should only be called when in a user context as it may
344          * try to sleep if there are no pages available, but that
345          * shouldn't be the case here.
346          */
347         s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
348         p->seg[SSEG] = s;
349         pg = newpage(1, 0, USTKTOP-BY2PG);
350         segpage(s, pg);
351         k = kmap(pg);
352         bootargs(VA(k));
353         kunmap(k);
354
355         /*
356          * Text
357          */
358         s = newseg(SG_TEXT, UTZERO, 1);
359         s->flushme++;
360         p->seg[TSEG] = s;
361         pg = newpage(1, 0, UTZERO);
362         pg->txtflush = ~0;
363         segpage(s, pg);
364         k = kmap(s->map[0]->pages[0]);
365         memset((void *)VA(k), 0, BY2PG);
366         memmove((ulong*)VA(k), initcode, sizeof initcode);
367         kunmap(k);
368
369         ready(p);
370 }
371
372 void
373 exit(int)
374 {
375         cpushutdown();
376         splhi();
377         arcs(0x18);     /* reboot */
378 }
379
380 void
381 reboot(void *, void *, ulong)
382 {
383 }
384
385 void
386 evenaddr(uintptr va)
387 {
388         if((va & 3) != 0){
389                 dumpstack();
390                 postnote(up, 1, "sys: odd address", NDebug);
391                 error(Ebadarg);
392         }
393 }
394
395 void
396 procsetup(Proc *p)
397 {
398         p->fpstate = FPinit;
399         memmove(p->fpsave, &initfp, sizeof(FPsave));
400
401         cycles(&p->kentry);
402         p->pcycles = -p->kentry;
403 }
404
405 void
406 procfork(Proc *p)
407 {
408         int s;
409
410         p->kentry = up->kentry;
411         p->pcycles = -p->kentry;
412
413         s = splhi();
414         switch(up->fpstate & ~FPillegal){
415         case FPactive:
416                 savefpregs(up->fpsave);
417                 up->fpstate = FPinactive;
418                 /* wet floor */
419         case FPinactive:
420                 memmove(p->fpsave, up->fpsave, sizeof(FPsave));
421                 p->fpstate = FPinactive;
422         }
423         splx(s);
424 }
425
426 void
427 procsave(Proc *p)
428 {
429         uvlong t;
430
431         if(p->fpstate == FPactive){
432                 if(p->state != Moribund) {
433                         savefpregs(p->fpsave);
434                         p->fpstate = FPinactive;
435                 }
436         }
437         
438         cycles(&t);
439         p->pcycles += t;
440 }
441
442 void
443 procrestore(Proc *p)
444 {
445         uvlong t;
446
447         if(p->kp)
448                 return;
449         cycles(&t);
450         p->pcycles -= t;
451 }
452
453 void
454 idlehands(void)
455 {
456 }
457
458 void
459 confinit(void)
460 {
461         ulong kpages;
462
463         /*
464          *  set up CPU's mach structure
465          *  cpu0's was zeroed in l.s and our stack is in Mach, so don't zero it.
466          */
467         m->machno = 0;
468         m->speed = 150;                 /* initial guess at MHz */
469         m->hz = m->speed * Mhz;
470         conf.nmach = 1;
471
472         /* set up other configuration parameters */
473         conf.nproc = 2000;
474         conf.nswap = 262144;
475         conf.nswppo = 4096;
476         conf.nimage = 200;
477
478         conf.copymode = 0;              /* copy on write */
479
480         kpages = conf.npage - (conf.npage*80)/100;
481         if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
482                 kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
483                 kpages += (conf.nproc*KSTACK)/BY2PG;
484         }
485         conf.upages = conf.npage - kpages;
486         conf.ialloc = (kpages/2)*BY2PG;
487
488         kpages *= BY2PG;
489         kpages -= conf.upages*sizeof(Page)
490                 + conf.nproc*sizeof(Proc)
491                 + conf.nimage*sizeof(Image)
492                 + conf.nswap
493                 + conf.nswppo*sizeof(Page*);
494         mainmem->maxsize = kpages;
495         imagmem->maxsize = kpages;
496 //      mainmem->flags |= POOL_PARANOIA;
497 }
498
499 void
500 setupwatchpts(Proc *, Watchpt *, int n)
501 {
502         if(n > 0)
503                 error("no watchpoints");
504 }
505
506 int
507 isaconfig(char *, int, ISAConf*)
508 {
509         return 0;
510 }