1*0c0b2b49SDavid du Colombier #include "u.h"
2*0c0b2b49SDavid du Colombier #include "../port/lib.h"
3*0c0b2b49SDavid du Colombier #include "mem.h"
4*0c0b2b49SDavid du Colombier #include "dat.h"
5*0c0b2b49SDavid du Colombier #include "fns.h"
6*0c0b2b49SDavid du Colombier #include "io.h"
7*0c0b2b49SDavid du Colombier #include "../ip/ip.h"
8*0c0b2b49SDavid du Colombier #include <pool.h>
9*0c0b2b49SDavid du Colombier #include <tos.h>
10*0c0b2b49SDavid du Colombier #include <bootexec.h>
11*0c0b2b49SDavid du Colombier #include "init.h"
12*0c0b2b49SDavid du Colombier
13*0c0b2b49SDavid du Colombier enum {
14*0c0b2b49SDavid du Colombier /* space for syscall args, return PC, top-of-stack struct */
15*0c0b2b49SDavid du Colombier Stkheadroom = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
16*0c0b2b49SDavid du Colombier };
17*0c0b2b49SDavid du Colombier
18*0c0b2b49SDavid du Colombier typedef struct mipsexec Mipsexec;
19*0c0b2b49SDavid du Colombier
20*0c0b2b49SDavid du Colombier #define MAXCONF 64
21*0c0b2b49SDavid du Colombier #define CONFBUFLEN 4096
22*0c0b2b49SDavid du Colombier #define MAXBOOTENV 256
23*0c0b2b49SDavid du Colombier
24*0c0b2b49SDavid du Colombier /* only for reboot */
25*0c0b2b49SDavid du Colombier #define BOOTARGS ((char*)(CONFADDR))
26*0c0b2b49SDavid du Colombier #define BOOTARGSLEN CONFBUFLEN
27*0c0b2b49SDavid du Colombier #define CONFARGVLEN (MAXCONF*BY2WD)
28*0c0b2b49SDavid du Colombier
29*0c0b2b49SDavid du Colombier /* args passed by boot loader for main(), addr in 32 bit */
30*0c0b2b49SDavid du Colombier int _argc;
31*0c0b2b49SDavid du Colombier long *_argv;
32*0c0b2b49SDavid du Colombier long *_env;
33*0c0b2b49SDavid du Colombier static char *bootenvname[MAXBOOTENV];
34*0c0b2b49SDavid du Colombier static char *bootenvval[MAXBOOTENV];
35*0c0b2b49SDavid du Colombier static int nenv;
36*0c0b2b49SDavid du Colombier
37*0c0b2b49SDavid du Colombier /* plan9.ini */
38*0c0b2b49SDavid du Colombier static char confbuf[CONFBUFLEN];
39*0c0b2b49SDavid du Colombier static char *confname[MAXCONF];
40*0c0b2b49SDavid du Colombier static char *confval[MAXCONF];
41*0c0b2b49SDavid du Colombier static int nconf;
42*0c0b2b49SDavid du Colombier
43*0c0b2b49SDavid du Colombier /*
44*0c0b2b49SDavid du Colombier * Option arguments from the command line.
45*0c0b2b49SDavid du Colombier * oargv[0] is the boot file.
46*0c0b2b49SDavid du Colombier */
47*0c0b2b49SDavid du Colombier static int oargc;
48*0c0b2b49SDavid du Colombier static char* oargv[20];
49*0c0b2b49SDavid du Colombier static char oargb[128];
50*0c0b2b49SDavid du Colombier static int oargblen;
51*0c0b2b49SDavid du Colombier
52*0c0b2b49SDavid du Colombier static uintptr sp; /* XXX - must go - user stack of init proc */
53*0c0b2b49SDavid du Colombier
54*0c0b2b49SDavid du Colombier /*
55*0c0b2b49SDavid du Colombier * software tlb simulation
56*0c0b2b49SDavid du Colombier */
57*0c0b2b49SDavid du Colombier static Softtlb stlb[MAXMACH][STLBSIZE];
58*0c0b2b49SDavid du Colombier
59*0c0b2b49SDavid du Colombier Mach *machaddr[MAXMACH];
60*0c0b2b49SDavid du Colombier Conf conf;
61*0c0b2b49SDavid du Colombier ulong memsize;
62*0c0b2b49SDavid du Colombier FPsave initfp;
63*0c0b2b49SDavid du Colombier
64*0c0b2b49SDavid du Colombier int normalprint;
65*0c0b2b49SDavid du Colombier ulong cpufreq;
66*0c0b2b49SDavid du Colombier
67*0c0b2b49SDavid du Colombier /*
68*0c0b2b49SDavid du Colombier * initialize a processor's mach structure. each processor does this
69*0c0b2b49SDavid du Colombier * for itself.
70*0c0b2b49SDavid du Colombier */
71*0c0b2b49SDavid du Colombier void
machinit(void)72*0c0b2b49SDavid du Colombier machinit(void)
73*0c0b2b49SDavid du Colombier {
74*0c0b2b49SDavid du Colombier /* Ensure CU1 is off */
75*0c0b2b49SDavid du Colombier clrfpintr();
76*0c0b2b49SDavid du Colombier
77*0c0b2b49SDavid du Colombier m->stb = &stlb[m->machno][0];
78*0c0b2b49SDavid du Colombier
79*0c0b2b49SDavid du Colombier clockinit();
80*0c0b2b49SDavid du Colombier }
81*0c0b2b49SDavid du Colombier
82*0c0b2b49SDavid du Colombier static void
optionsinit(char * s)83*0c0b2b49SDavid du Colombier optionsinit(char* s)
84*0c0b2b49SDavid du Colombier {
85*0c0b2b49SDavid du Colombier strecpy(oargb, oargb+sizeof(oargb), s);
86*0c0b2b49SDavid du Colombier
87*0c0b2b49SDavid du Colombier oargblen = strlen(oargb);
88*0c0b2b49SDavid du Colombier oargc = tokenize(oargb, oargv, nelem(oargv)-1);
89*0c0b2b49SDavid du Colombier oargv[oargc] = nil;
90*0c0b2b49SDavid du Colombier }
91*0c0b2b49SDavid du Colombier
92*0c0b2b49SDavid du Colombier void
plan9iniinit(void)93*0c0b2b49SDavid du Colombier plan9iniinit(void)
94*0c0b2b49SDavid du Colombier {
95*0c0b2b49SDavid du Colombier char *cp;
96*0c0b2b49SDavid du Colombier int i;
97*0c0b2b49SDavid du Colombier
98*0c0b2b49SDavid du Colombier nconf = 0;
99*0c0b2b49SDavid du Colombier if(_argv != nil){
100*0c0b2b49SDavid du Colombier memmove(confbuf, (char*)_argv[0], sizeof(confbuf));
101*0c0b2b49SDavid du Colombier for(i=1; i<_argc && nconf<MAXCONF; i++){
102*0c0b2b49SDavid du Colombier _argv[i] += (long)confbuf - _argv[0];
103*0c0b2b49SDavid du Colombier if(*(char*)_argv[i] == '#')
104*0c0b2b49SDavid du Colombier continue;
105*0c0b2b49SDavid du Colombier cp = strchr((char*)_argv[i], '=');
106*0c0b2b49SDavid du Colombier if(cp == nil)
107*0c0b2b49SDavid du Colombier continue;
108*0c0b2b49SDavid du Colombier *cp++ = '\0';
109*0c0b2b49SDavid du Colombier confname[nconf] = (char*)_argv[i];
110*0c0b2b49SDavid du Colombier confval[nconf] = cp;
111*0c0b2b49SDavid du Colombier nconf++;
112*0c0b2b49SDavid du Colombier }
113*0c0b2b49SDavid du Colombier }
114*0c0b2b49SDavid du Colombier
115*0c0b2b49SDavid du Colombier nenv = 0;
116*0c0b2b49SDavid du Colombier if(_env != nil)
117*0c0b2b49SDavid du Colombier for(i=0; (char*)_env[i] != nil && nenv<MAXBOOTENV; i++){
118*0c0b2b49SDavid du Colombier if(*(char*)_env[i] == '#')
119*0c0b2b49SDavid du Colombier continue;
120*0c0b2b49SDavid du Colombier cp = strchr((char*)_env[i], '=');
121*0c0b2b49SDavid du Colombier if(cp == nil)
122*0c0b2b49SDavid du Colombier continue;
123*0c0b2b49SDavid du Colombier *cp++ = '\0';
124*0c0b2b49SDavid du Colombier bootenvname[nenv] = (char*)_env[i];
125*0c0b2b49SDavid du Colombier bootenvval[nenv] = cp;
126*0c0b2b49SDavid du Colombier nenv++;
127*0c0b2b49SDavid du Colombier }
128*0c0b2b49SDavid du Colombier }
129*0c0b2b49SDavid du Colombier
130*0c0b2b49SDavid du Colombier static int
findconf(char * name)131*0c0b2b49SDavid du Colombier findconf(char *name)
132*0c0b2b49SDavid du Colombier {
133*0c0b2b49SDavid du Colombier int i;
134*0c0b2b49SDavid du Colombier
135*0c0b2b49SDavid du Colombier for(i = 0; i < nconf; i++)
136*0c0b2b49SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
137*0c0b2b49SDavid du Colombier return i;
138*0c0b2b49SDavid du Colombier return -1;
139*0c0b2b49SDavid du Colombier }
140*0c0b2b49SDavid du Colombier
141*0c0b2b49SDavid du Colombier char*
getconf(char * name)142*0c0b2b49SDavid du Colombier getconf(char *name)
143*0c0b2b49SDavid du Colombier {
144*0c0b2b49SDavid du Colombier int i;
145*0c0b2b49SDavid du Colombier
146*0c0b2b49SDavid du Colombier i = findconf(name);
147*0c0b2b49SDavid du Colombier if(i >= 0)
148*0c0b2b49SDavid du Colombier return confval[i];
149*0c0b2b49SDavid du Colombier return nil;
150*0c0b2b49SDavid du Colombier }
151*0c0b2b49SDavid du Colombier
152*0c0b2b49SDavid du Colombier static int
findbootenv(char * name)153*0c0b2b49SDavid du Colombier findbootenv(char *name)
154*0c0b2b49SDavid du Colombier {
155*0c0b2b49SDavid du Colombier int i;
156*0c0b2b49SDavid du Colombier
157*0c0b2b49SDavid du Colombier for(i = 0; i < nenv; i++)
158*0c0b2b49SDavid du Colombier if(cistrcmp(bootenvname[i], name) == 0)
159*0c0b2b49SDavid du Colombier return i;
160*0c0b2b49SDavid du Colombier return -1;
161*0c0b2b49SDavid du Colombier }
162*0c0b2b49SDavid du Colombier
163*0c0b2b49SDavid du Colombier static char*
getbootenv(char * name)164*0c0b2b49SDavid du Colombier getbootenv(char *name)
165*0c0b2b49SDavid du Colombier {
166*0c0b2b49SDavid du Colombier int i;
167*0c0b2b49SDavid du Colombier
168*0c0b2b49SDavid du Colombier i = findbootenv(name);
169*0c0b2b49SDavid du Colombier if(i >= 0)
170*0c0b2b49SDavid du Colombier return bootenvval[i];
171*0c0b2b49SDavid du Colombier return nil;
172*0c0b2b49SDavid du Colombier }
173*0c0b2b49SDavid du Colombier
174*0c0b2b49SDavid du Colombier void
confinit(void)175*0c0b2b49SDavid du Colombier confinit(void)
176*0c0b2b49SDavid du Colombier {
177*0c0b2b49SDavid du Colombier char *p;
178*0c0b2b49SDavid du Colombier int i;
179*0c0b2b49SDavid du Colombier ulong kpages, ktop;
180*0c0b2b49SDavid du Colombier ulong maxmem, highmemsize;
181*0c0b2b49SDavid du Colombier
182*0c0b2b49SDavid du Colombier /* memory size */
183*0c0b2b49SDavid du Colombier memsize = MEMSIZE;
184*0c0b2b49SDavid du Colombier if((p = getbootenv("memsize")) != nil)
185*0c0b2b49SDavid du Colombier memsize = strtoul(p, 0, 0) * MB;
186*0c0b2b49SDavid du Colombier highmemsize = 0;
187*0c0b2b49SDavid du Colombier if((p = getbootenv("highmemsize")) != nil)
188*0c0b2b49SDavid du Colombier highmemsize = strtoul(p, 0, 0) * MB;
189*0c0b2b49SDavid du Colombier if((p = getconf("*maxmem")) != nil){
190*0c0b2b49SDavid du Colombier maxmem = strtoul(p, 0, 0);
191*0c0b2b49SDavid du Colombier memsize = MIN(memsize, maxmem);
192*0c0b2b49SDavid du Colombier maxmem -= memsize;
193*0c0b2b49SDavid du Colombier highmemsize = MIN(highmemsize, maxmem);
194*0c0b2b49SDavid du Colombier if(memsize < 16*MB) /* sanity */
195*0c0b2b49SDavid du Colombier memsize = 16*MB;
196*0c0b2b49SDavid du Colombier }
197*0c0b2b49SDavid du Colombier
198*0c0b2b49SDavid du Colombier /* set up other configuration parameters */
199*0c0b2b49SDavid du Colombier conf.nproc = 2000;
200*0c0b2b49SDavid du Colombier conf.nswap = 262144;
201*0c0b2b49SDavid du Colombier conf.nswppo = 4096;
202*0c0b2b49SDavid du Colombier conf.nimage = 200;
203*0c0b2b49SDavid du Colombier
204*0c0b2b49SDavid du Colombier /*
205*0c0b2b49SDavid du Colombier * divide memory to user pages and kernel.
206*0c0b2b49SDavid du Colombier */
207*0c0b2b49SDavid du Colombier conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
208*0c0b2b49SDavid du Colombier conf.mem[0].npage = memsize/BY2PG - ktop/BY2PG;
209*0c0b2b49SDavid du Colombier
210*0c0b2b49SDavid du Colombier conf.mem[1].base = HIGHMEM;
211*0c0b2b49SDavid du Colombier conf.mem[1].npage = highmemsize/BY2PG;
212*0c0b2b49SDavid du Colombier
213*0c0b2b49SDavid du Colombier conf.npage = 0;
214*0c0b2b49SDavid du Colombier for(i=0; i<nelem(conf.mem); i++)
215*0c0b2b49SDavid du Colombier conf.npage += conf.mem[i].npage;
216*0c0b2b49SDavid du Colombier
217*0c0b2b49SDavid du Colombier kpages = conf.npage - (conf.npage*80)/100;
218*0c0b2b49SDavid du Colombier if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
219*0c0b2b49SDavid du Colombier kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
220*0c0b2b49SDavid du Colombier kpages += (conf.nproc*KSTACK)/BY2PG;
221*0c0b2b49SDavid du Colombier }
222*0c0b2b49SDavid du Colombier conf.upages = conf.npage - kpages;
223*0c0b2b49SDavid du Colombier conf.ialloc = (kpages/2)*BY2PG;
224*0c0b2b49SDavid du Colombier
225*0c0b2b49SDavid du Colombier kpages *= BY2PG;
226*0c0b2b49SDavid du Colombier kpages -= conf.upages*sizeof(Page)
227*0c0b2b49SDavid du Colombier + conf.nproc*sizeof(Proc)
228*0c0b2b49SDavid du Colombier + conf.nimage*sizeof(Image)
229*0c0b2b49SDavid du Colombier + conf.nswap
230*0c0b2b49SDavid du Colombier + conf.nswppo*sizeof(Page);
231*0c0b2b49SDavid du Colombier mainmem->maxsize = kpages;
232*0c0b2b49SDavid du Colombier
233*0c0b2b49SDavid du Colombier /*
234*0c0b2b49SDavid du Colombier * set up CPU's mach structure
235*0c0b2b49SDavid du Colombier * cpu0's was zeroed in main() and our stack is in Mach, so don't zero it.
236*0c0b2b49SDavid du Colombier */
237*0c0b2b49SDavid du Colombier m->machno = 0;
238*0c0b2b49SDavid du Colombier m->hz = cpufreq; /* initial guess at MHz */
239*0c0b2b49SDavid du Colombier m->speed = m->hz / Mhz;
240*0c0b2b49SDavid du Colombier conf.nmach = 1;
241*0c0b2b49SDavid du Colombier
242*0c0b2b49SDavid du Colombier conf.nuart = 1;
243*0c0b2b49SDavid du Colombier conf.copymode = 0; /* copy on write */
244*0c0b2b49SDavid du Colombier }
245*0c0b2b49SDavid du Colombier
246*0c0b2b49SDavid du Colombier void
procrestore(Proc * p)247*0c0b2b49SDavid du Colombier procrestore(Proc *p)
248*0c0b2b49SDavid du Colombier {
249*0c0b2b49SDavid du Colombier uvlong t;
250*0c0b2b49SDavid du Colombier
251*0c0b2b49SDavid du Colombier if(p->kp)
252*0c0b2b49SDavid du Colombier return;
253*0c0b2b49SDavid du Colombier cycles(&t);
254*0c0b2b49SDavid du Colombier p->pcycles -= t;
255*0c0b2b49SDavid du Colombier }
256*0c0b2b49SDavid du Colombier
257*0c0b2b49SDavid du Colombier /*
258*0c0b2b49SDavid du Colombier * Save the mach dependent part of the process state.
259*0c0b2b49SDavid du Colombier */
260*0c0b2b49SDavid du Colombier void
procsave(Proc * p)261*0c0b2b49SDavid du Colombier procsave(Proc *p)
262*0c0b2b49SDavid du Colombier {
263*0c0b2b49SDavid du Colombier uvlong t;
264*0c0b2b49SDavid du Colombier
265*0c0b2b49SDavid du Colombier cycles(&t);
266*0c0b2b49SDavid du Colombier p->pcycles += t;
267*0c0b2b49SDavid du Colombier //fpuprocsave(); // XXX
268*0c0b2b49SDavid du Colombier }
269*0c0b2b49SDavid du Colombier
270*0c0b2b49SDavid du Colombier static void
fmtinit(void)271*0c0b2b49SDavid du Colombier fmtinit(void)
272*0c0b2b49SDavid du Colombier {
273*0c0b2b49SDavid du Colombier printinit();
274*0c0b2b49SDavid du Colombier quotefmtinstall();
275*0c0b2b49SDavid du Colombier /* ipreset installs these when chandevreset runs */
276*0c0b2b49SDavid du Colombier fmtinstall('i', eipfmt);
277*0c0b2b49SDavid du Colombier fmtinstall('I', eipfmt);
278*0c0b2b49SDavid du Colombier fmtinstall('E', eipfmt);
279*0c0b2b49SDavid du Colombier fmtinstall('V', eipfmt);
280*0c0b2b49SDavid du Colombier fmtinstall('M', eipfmt);
281*0c0b2b49SDavid du Colombier }
282*0c0b2b49SDavid du Colombier
283*0c0b2b49SDavid du Colombier /*
284*0c0b2b49SDavid du Colombier * setup MIPS trap vectors
285*0c0b2b49SDavid du Colombier */
286*0c0b2b49SDavid du Colombier void
vecinit(void)287*0c0b2b49SDavid du Colombier vecinit(void)
288*0c0b2b49SDavid du Colombier {
289*0c0b2b49SDavid du Colombier memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
290*0c0b2b49SDavid du Colombier memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
291*0c0b2b49SDavid du Colombier memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
292*0c0b2b49SDavid du Colombier memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
293*0c0b2b49SDavid du Colombier /* 0x200 not used in looongson 2e */
294*0c0b2b49SDavid du Colombier icflush((ulong*)UTLBMISS, 4*1024);
295*0c0b2b49SDavid du Colombier
296*0c0b2b49SDavid du Colombier setstatus(getstatus() & ~BEV);
297*0c0b2b49SDavid du Colombier }
298*0c0b2b49SDavid du Colombier
299*0c0b2b49SDavid du Colombier static void
prcpuid(void)300*0c0b2b49SDavid du Colombier prcpuid(void)
301*0c0b2b49SDavid du Colombier {
302*0c0b2b49SDavid du Colombier ulong cpuid, cfg;
303*0c0b2b49SDavid du Colombier char *cpu;
304*0c0b2b49SDavid du Colombier
305*0c0b2b49SDavid du Colombier cpuid = prid();
306*0c0b2b49SDavid du Colombier cfg = getconfig();
307*0c0b2b49SDavid du Colombier if (((cpuid>>16) & MASK(8)) == 0) /* vendor */
308*0c0b2b49SDavid du Colombier cpu = "old mips";
309*0c0b2b49SDavid du Colombier else if (((cpuid>>16) & MASK(8)) == 1)
310*0c0b2b49SDavid du Colombier switch ((cpuid>>8) & MASK(8)) { /* processor */
311*0c0b2b49SDavid du Colombier case 0x93:
312*0c0b2b49SDavid du Colombier cpu = "mips 24k";
313*0c0b2b49SDavid du Colombier break;
314*0c0b2b49SDavid du Colombier case 0x96:
315*0c0b2b49SDavid du Colombier cpu = "mips 24ke";
316*0c0b2b49SDavid du Colombier break;
317*0c0b2b49SDavid du Colombier default:
318*0c0b2b49SDavid du Colombier cpu = "mips";
319*0c0b2b49SDavid du Colombier break;
320*0c0b2b49SDavid du Colombier }
321*0c0b2b49SDavid du Colombier else
322*0c0b2b49SDavid du Colombier cpu = "other mips";
323*0c0b2b49SDavid du Colombier delay(200);
324*0c0b2b49SDavid du Colombier print("cpu%d: %ldMHz %s %se 0x%ulx v%ld.%ld rev %ld has fpu\n",
325*0c0b2b49SDavid du Colombier m->machno, m->hz / Mhz, cpu, cfg & (1<<15)? "b": "l",
326*0c0b2b49SDavid du Colombier (cpuid>>8) & MASK(8), (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3),
327*0c0b2b49SDavid du Colombier cpuid & MASK(2));
328*0c0b2b49SDavid du Colombier delay(200);
329*0c0b2b49SDavid du Colombier
330*0c0b2b49SDavid du Colombier print("cpu%d: %d tlb entries, using %dK pages\n", m->machno,
331*0c0b2b49SDavid du Colombier 64, BY2PG/1024);
332*0c0b2b49SDavid du Colombier delay(50);
333*0c0b2b49SDavid du Colombier print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
334*0c0b2b49SDavid du Colombier 32 << ((cfg>>9) & MASK(3)));
335*0c0b2b49SDavid du Colombier delay(50);
336*0c0b2b49SDavid du Colombier print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
337*0c0b2b49SDavid du Colombier 32 << ((cfg>>6) & MASK(3)));
338*0c0b2b49SDavid du Colombier delay(500);
339*0c0b2b49SDavid du Colombier }
340*0c0b2b49SDavid du Colombier
341*0c0b2b49SDavid du Colombier static int
ckpagemask(ulong mask,ulong size)342*0c0b2b49SDavid du Colombier ckpagemask(ulong mask, ulong size)
343*0c0b2b49SDavid du Colombier {
344*0c0b2b49SDavid du Colombier int s;
345*0c0b2b49SDavid du Colombier ulong pm;
346*0c0b2b49SDavid du Colombier
347*0c0b2b49SDavid du Colombier s = splhi();
348*0c0b2b49SDavid du Colombier setpagemask(mask);
349*0c0b2b49SDavid du Colombier pm = getpagemask();
350*0c0b2b49SDavid du Colombier splx(s);
351*0c0b2b49SDavid du Colombier if(pm != mask){
352*0c0b2b49SDavid du Colombier iprint("page size %ldK not supported on this cpu; "
353*0c0b2b49SDavid du Colombier "mask %#lux read back as %#lux\n", size/1024, mask, pm);
354*0c0b2b49SDavid du Colombier return -1;
355*0c0b2b49SDavid du Colombier }
356*0c0b2b49SDavid du Colombier return 0;
357*0c0b2b49SDavid du Colombier }
358*0c0b2b49SDavid du Colombier
359*0c0b2b49SDavid du Colombier void
init0(void)360*0c0b2b49SDavid du Colombier init0(void)
361*0c0b2b49SDavid du Colombier {
362*0c0b2b49SDavid du Colombier char buf[128];
363*0c0b2b49SDavid du Colombier int i;
364*0c0b2b49SDavid du Colombier
365*0c0b2b49SDavid du Colombier up->nerrlab = 0;
366*0c0b2b49SDavid du Colombier
367*0c0b2b49SDavid du Colombier spllo();
368*0c0b2b49SDavid du Colombier
369*0c0b2b49SDavid du Colombier /*
370*0c0b2b49SDavid du Colombier * These are o.k. because rootinit is null.
371*0c0b2b49SDavid du Colombier * Then early kproc's will have a root and dot.
372*0c0b2b49SDavid du Colombier */
373*0c0b2b49SDavid du Colombier up->slash = namec("#/", Atodir, 0, 0);
374*0c0b2b49SDavid du Colombier pathclose(up->slash->path);
375*0c0b2b49SDavid du Colombier up->slash->path = newpath("/");
376*0c0b2b49SDavid du Colombier up->dot = cclone(up->slash);
377*0c0b2b49SDavid du Colombier
378*0c0b2b49SDavid du Colombier chandevinit();
379*0c0b2b49SDavid du Colombier
380*0c0b2b49SDavid du Colombier if(!waserror()){
381*0c0b2b49SDavid du Colombier ksetenv("cputype", "spim64", 0);
382*0c0b2b49SDavid du Colombier snprint(buf, sizeof buf, "spim64 %s loongson 2f", conffile);
383*0c0b2b49SDavid du Colombier ksetenv("terminal", buf, 0);
384*0c0b2b49SDavid du Colombier if(cpuserver)
385*0c0b2b49SDavid du Colombier ksetenv("service", "cpu", 0);
386*0c0b2b49SDavid du Colombier else
387*0c0b2b49SDavid du Colombier ksetenv("service", "terminal", 0);
388*0c0b2b49SDavid du Colombier // ksetenv("nobootprompt", "local!/boot/bzroot", 0); // for bzroot
389*0c0b2b49SDavid du Colombier ksetenv("nvram", "/boot/nvram", 0);
390*0c0b2b49SDavid du Colombier /* convert plan9.ini variables to #e and #ec */
391*0c0b2b49SDavid du Colombier for(i = 0; i < nconf; i++) {
392*0c0b2b49SDavid du Colombier if(*confname[i] == '*')
393*0c0b2b49SDavid du Colombier continue;
394*0c0b2b49SDavid du Colombier ksetenv(confname[i], confval[i], 0);
395*0c0b2b49SDavid du Colombier ksetenv(confname[i], confval[i], 1);
396*0c0b2b49SDavid du Colombier }
397*0c0b2b49SDavid du Colombier poperror();
398*0c0b2b49SDavid du Colombier }
399*0c0b2b49SDavid du Colombier kproc("alarm", alarmkproc, 0);
400*0c0b2b49SDavid du Colombier // i8250console();
401*0c0b2b49SDavid du Colombier touser(sp);
402*0c0b2b49SDavid du Colombier }
403*0c0b2b49SDavid du Colombier
404*0c0b2b49SDavid du Colombier static void
bootargs(uintptr base)405*0c0b2b49SDavid du Colombier bootargs(uintptr base)
406*0c0b2b49SDavid du Colombier {
407*0c0b2b49SDavid du Colombier int i;
408*0c0b2b49SDavid du Colombier uintptr ssize;
409*0c0b2b49SDavid du Colombier char **av, *p;
410*0c0b2b49SDavid du Colombier
411*0c0b2b49SDavid du Colombier /*
412*0c0b2b49SDavid du Colombier * Push the boot args onto the stack.
413*0c0b2b49SDavid du Colombier * The initial value of the user stack must be such
414*0c0b2b49SDavid du Colombier * that the total used is larger than the maximum size
415*0c0b2b49SDavid du Colombier * of the argument list checked in syscall.
416*0c0b2b49SDavid du Colombier */
417*0c0b2b49SDavid du Colombier i = oargblen+1;
418*0c0b2b49SDavid du Colombier p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));
419*0c0b2b49SDavid du Colombier memmove(p, oargb, i);
420*0c0b2b49SDavid du Colombier
421*0c0b2b49SDavid du Colombier /*
422*0c0b2b49SDavid du Colombier * Now push the argv pointers.
423*0c0b2b49SDavid du Colombier * The code jumped to by touser in l.s expects arguments
424*0c0b2b49SDavid du Colombier * main(char* argv0, ...)
425*0c0b2b49SDavid du Colombier * and calls
426*0c0b2b49SDavid du Colombier * startboot("/boot/boot", &argv0)
427*0c0b2b49SDavid du Colombier * not the usual (int argc, char* argv[])
428*0c0b2b49SDavid du Colombier */
429*0c0b2b49SDavid du Colombier av = (char**)(p - (oargc+1)*sizeof(char*));
430*0c0b2b49SDavid du Colombier ssize = base + BY2PG - PTR2UINT(av);
431*0c0b2b49SDavid du Colombier for(i = 0; i < oargc; i++)
432*0c0b2b49SDavid du Colombier *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
433*0c0b2b49SDavid du Colombier *av = nil;
434*0c0b2b49SDavid du Colombier sp = USTKTOP - ssize;
435*0c0b2b49SDavid du Colombier }
436*0c0b2b49SDavid du Colombier
437*0c0b2b49SDavid du Colombier void
userinit(void)438*0c0b2b49SDavid du Colombier userinit(void)
439*0c0b2b49SDavid du Colombier {
440*0c0b2b49SDavid du Colombier Proc *p;
441*0c0b2b49SDavid du Colombier KMap *k;
442*0c0b2b49SDavid du Colombier Page *pg;
443*0c0b2b49SDavid du Colombier Segment *s;
444*0c0b2b49SDavid du Colombier
445*0c0b2b49SDavid du Colombier p = newproc();
446*0c0b2b49SDavid du Colombier p->pgrp = newpgrp();
447*0c0b2b49SDavid du Colombier p->egrp = smalloc(sizeof(Egrp));
448*0c0b2b49SDavid du Colombier p->egrp->ref = 1;
449*0c0b2b49SDavid du Colombier p->fgrp = dupfgrp(nil);
450*0c0b2b49SDavid du Colombier p->rgrp = newrgrp();
451*0c0b2b49SDavid du Colombier p->procmode = 0640;
452*0c0b2b49SDavid du Colombier
453*0c0b2b49SDavid du Colombier kstrdup(&eve, "");
454*0c0b2b49SDavid du Colombier kstrdup(&p->text, "*init*");
455*0c0b2b49SDavid du Colombier kstrdup(&p->user, eve);
456*0c0b2b49SDavid du Colombier
457*0c0b2b49SDavid du Colombier p->fpstate = FPinit;
458*0c0b2b49SDavid du Colombier p->fpsave.fpstatus = initfp.fpstatus;
459*0c0b2b49SDavid du Colombier
460*0c0b2b49SDavid du Colombier /*
461*0c0b2b49SDavid du Colombier * Kernel Stack
462*0c0b2b49SDavid du Colombier */
463*0c0b2b49SDavid du Colombier p->sched.pc = (uintptr)init0;
464*0c0b2b49SDavid du Colombier p->sched.sp = (uintptr)p->kstack+KSTACK-Stkheadroom;
465*0c0b2b49SDavid du Colombier p->sched.sp = STACKALIGN(p->sched.sp);
466*0c0b2b49SDavid du Colombier
467*0c0b2b49SDavid du Colombier /*
468*0c0b2b49SDavid du Colombier * User Stack
469*0c0b2b49SDavid du Colombier *
470*0c0b2b49SDavid du Colombier * Technically, newpage can't be called here because it
471*0c0b2b49SDavid du Colombier * should only be called when in a user context as it may
472*0c0b2b49SDavid du Colombier * try to sleep if there are no pages available, but that
473*0c0b2b49SDavid du Colombier * shouldn't be the case here.
474*0c0b2b49SDavid du Colombier */
475*0c0b2b49SDavid du Colombier s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
476*0c0b2b49SDavid du Colombier p->seg[SSEG] = s;
477*0c0b2b49SDavid du Colombier pg = newpage(1, 0, USTKTOP-BY2PG);
478*0c0b2b49SDavid du Colombier memset(pg->cachectl, PG_DATFLUSH, sizeof(pg->cachectl));
479*0c0b2b49SDavid du Colombier segpage(s, pg);
480*0c0b2b49SDavid du Colombier k = kmap(pg);
481*0c0b2b49SDavid du Colombier bootargs(VA(k));
482*0c0b2b49SDavid du Colombier kunmap(k);
483*0c0b2b49SDavid du Colombier
484*0c0b2b49SDavid du Colombier /*
485*0c0b2b49SDavid du Colombier * Text
486*0c0b2b49SDavid du Colombier */
487*0c0b2b49SDavid du Colombier s = newseg(SG_TEXT, UTZERO, 1);
488*0c0b2b49SDavid du Colombier s->flushme++;
489*0c0b2b49SDavid du Colombier p->seg[TSEG] = s;
490*0c0b2b49SDavid du Colombier pg = newpage(1, 0, UTZERO);
491*0c0b2b49SDavid du Colombier memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
492*0c0b2b49SDavid du Colombier segpage(s, pg);
493*0c0b2b49SDavid du Colombier k = kmap(s->map[0]->pages[0]);
494*0c0b2b49SDavid du Colombier memset((void*)VA(k), 0, BY2PG);
495*0c0b2b49SDavid du Colombier memmove((ulong*)VA(k), initcode, sizeof initcode);
496*0c0b2b49SDavid du Colombier kunmap(k);
497*0c0b2b49SDavid du Colombier
498*0c0b2b49SDavid du Colombier ready(p);
499*0c0b2b49SDavid du Colombier }
500*0c0b2b49SDavid du Colombier
501*0c0b2b49SDavid du Colombier /* called from rebootcmd() */
502*0c0b2b49SDavid du Colombier int
parsemipsboothdr(Chan * c,ulong magic,Execvals * evp)503*0c0b2b49SDavid du Colombier parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
504*0c0b2b49SDavid du Colombier {
505*0c0b2b49SDavid du Colombier long extra;
506*0c0b2b49SDavid du Colombier Mipsexec me;
507*0c0b2b49SDavid du Colombier
508*0c0b2b49SDavid du Colombier /*
509*0c0b2b49SDavid du Colombier * BOOT_MAGIC is sometimes defined like this:
510*0c0b2b49SDavid du Colombier * #define BOOT_MAGIC (0x160<<16) || magic == ((0x160<<16)|3)
511*0c0b2b49SDavid du Colombier * so we can only use it in a fairly stylized manner.
512*0c0b2b49SDavid du Colombier */
513*0c0b2b49SDavid du Colombier if(magic == BOOT_MAGIC) {
514*0c0b2b49SDavid du Colombier c->offset = 0; /* back up */
515*0c0b2b49SDavid du Colombier readn(c, &me, sizeof me);
516*0c0b2b49SDavid du Colombier /* if binary is -H1, read an extra long */
517*0c0b2b49SDavid du Colombier if (l2be(me.amagic) == 0407 && me.nscns == 0)
518*0c0b2b49SDavid du Colombier readn(c, &extra, sizeof extra);
519*0c0b2b49SDavid du Colombier evp->entry = l2be(me.mentry);
520*0c0b2b49SDavid du Colombier evp->textsize = l2be(me.tsize);
521*0c0b2b49SDavid du Colombier evp->datasize = l2be(me.dsize);
522*0c0b2b49SDavid du Colombier return 0;
523*0c0b2b49SDavid du Colombier } else
524*0c0b2b49SDavid du Colombier return -1;
525*0c0b2b49SDavid du Colombier }
526*0c0b2b49SDavid du Colombier
527*0c0b2b49SDavid du Colombier void
main(void)528*0c0b2b49SDavid du Colombier main(void)
529*0c0b2b49SDavid du Colombier {
530*0c0b2b49SDavid du Colombier extern char edata[], end[];
531*0c0b2b49SDavid du Colombier
532*0c0b2b49SDavid du Colombier m = (Mach*)MACHADDR;
533*0c0b2b49SDavid du Colombier memset(m, 0, sizeof(Mach)); /* clear Mach */
534*0c0b2b49SDavid du Colombier m->machno = 0;
535*0c0b2b49SDavid du Colombier machaddr[m->machno] = m;
536*0c0b2b49SDavid du Colombier up = nil;
537*0c0b2b49SDavid du Colombier memset(edata, 0, end-edata); /* clear bss */
538*0c0b2b49SDavid du Colombier
539*0c0b2b49SDavid du Colombier optionsinit("/boot/boot boot");
540*0c0b2b49SDavid du Colombier plan9iniinit();
541*0c0b2b49SDavid du Colombier confinit();
542*0c0b2b49SDavid du Colombier savefpregs(&initfp);
543*0c0b2b49SDavid du Colombier
544*0c0b2b49SDavid du Colombier machinit();
545*0c0b2b49SDavid du Colombier active.exiting = 0;
546*0c0b2b49SDavid du Colombier active.machs = 1;
547*0c0b2b49SDavid du Colombier
548*0c0b2b49SDavid du Colombier kmapinit();
549*0c0b2b49SDavid du Colombier xinit();
550*0c0b2b49SDavid du Colombier screeninit();
551*0c0b2b49SDavid du Colombier
552*0c0b2b49SDavid du Colombier ckpagemask(PGSZ, BY2PG);
553*0c0b2b49SDavid du Colombier tlbinit();
554*0c0b2b49SDavid du Colombier machwire();
555*0c0b2b49SDavid du Colombier
556*0c0b2b49SDavid du Colombier timersinit();
557*0c0b2b49SDavid du Colombier fmtinit();
558*0c0b2b49SDavid du Colombier vecinit();
559*0c0b2b49SDavid du Colombier
560*0c0b2b49SDavid du Colombier normalprint = 1;
561*0c0b2b49SDavid du Colombier print("\nPlan 9\n");
562*0c0b2b49SDavid du Colombier prcpuid();
563*0c0b2b49SDavid du Colombier if(PTECACHABILITY == PTENONCOHERWT)
564*0c0b2b49SDavid du Colombier print("caches configured as write-through\n");
565*0c0b2b49SDavid du Colombier // xsummary();
566*0c0b2b49SDavid du Colombier
567*0c0b2b49SDavid du Colombier i8259init();
568*0c0b2b49SDavid du Colombier kbdinit();
569*0c0b2b49SDavid du Colombier if(conf.monitor)
570*0c0b2b49SDavid du Colombier swcursorinit();
571*0c0b2b49SDavid du Colombier
572*0c0b2b49SDavid du Colombier pageinit();
573*0c0b2b49SDavid du Colombier procinit0();
574*0c0b2b49SDavid du Colombier initseg();
575*0c0b2b49SDavid du Colombier links();
576*0c0b2b49SDavid du Colombier chandevreset();
577*0c0b2b49SDavid du Colombier
578*0c0b2b49SDavid du Colombier swapinit();
579*0c0b2b49SDavid du Colombier userinit();
580*0c0b2b49SDavid du Colombier parseboothdr = parsemipsboothdr;
581*0c0b2b49SDavid du Colombier schedinit();
582*0c0b2b49SDavid du Colombier panic("schedinit returned");
583*0c0b2b49SDavid du Colombier }
584*0c0b2b49SDavid du Colombier
585*0c0b2b49SDavid du Colombier static void
writeconf(void)586*0c0b2b49SDavid du Colombier writeconf(void)
587*0c0b2b49SDavid du Colombier {
588*0c0b2b49SDavid du Colombier char *p, *q;
589*0c0b2b49SDavid du Colombier int n;
590*0c0b2b49SDavid du Colombier
591*0c0b2b49SDavid du Colombier p = getconfenv();
592*0c0b2b49SDavid du Colombier
593*0c0b2b49SDavid du Colombier if(waserror()) {
594*0c0b2b49SDavid du Colombier free(p);
595*0c0b2b49SDavid du Colombier nexterror();
596*0c0b2b49SDavid du Colombier }
597*0c0b2b49SDavid du Colombier
598*0c0b2b49SDavid du Colombier /* convert to name=value\0 format */
599*0c0b2b49SDavid du Colombier _argc = 1; /* skip _argv[0] */
600*0c0b2b49SDavid du Colombier _argv = (void*)CONFARGV;
601*0c0b2b49SDavid du Colombier _argv[0] = (long)BOOTARGS;
602*0c0b2b49SDavid du Colombier for(q=p; *q; q++) {
603*0c0b2b49SDavid du Colombier _argv[_argc] = (long)((uintptr)BOOTARGS + (q - p));
604*0c0b2b49SDavid du Colombier _argc++;
605*0c0b2b49SDavid du Colombier q += strlen(q);
606*0c0b2b49SDavid du Colombier *q = '=';
607*0c0b2b49SDavid du Colombier q += strlen(q);
608*0c0b2b49SDavid du Colombier }
609*0c0b2b49SDavid du Colombier n = q - p + 1;
610*0c0b2b49SDavid du Colombier _env = &_argv[_argc];
611*0c0b2b49SDavid du Colombier
612*0c0b2b49SDavid du Colombier if(n >= BOOTARGSLEN || (uintptr)_env >= CONFARGV + CONFARGVLEN)
613*0c0b2b49SDavid du Colombier error("kernel configuration too large");
614*0c0b2b49SDavid du Colombier memmove(BOOTARGS, p, n);
615*0c0b2b49SDavid du Colombier memset(BOOTARGS + n, '\0', BOOTARGSLEN - n);
616*0c0b2b49SDavid du Colombier memset(_env, 0, CONFARGV + CONFARGVLEN - (uintptr)_env);
617*0c0b2b49SDavid du Colombier
618*0c0b2b49SDavid du Colombier poperror();
619*0c0b2b49SDavid du Colombier free(p);
620*0c0b2b49SDavid du Colombier }
621*0c0b2b49SDavid du Colombier
622*0c0b2b49SDavid du Colombier static void
shutdown(int ispanic)623*0c0b2b49SDavid du Colombier shutdown(int ispanic)
624*0c0b2b49SDavid du Colombier {
625*0c0b2b49SDavid du Colombier int ms, once;
626*0c0b2b49SDavid du Colombier
627*0c0b2b49SDavid du Colombier ilock(&active);
628*0c0b2b49SDavid du Colombier if(ispanic)
629*0c0b2b49SDavid du Colombier active.ispanic = ispanic;
630*0c0b2b49SDavid du Colombier else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
631*0c0b2b49SDavid du Colombier active.ispanic = 0;
632*0c0b2b49SDavid du Colombier once = active.machs & (1<<m->machno);
633*0c0b2b49SDavid du Colombier /*
634*0c0b2b49SDavid du Colombier * setting exiting will make hzclock() on each processor call exit(0),
635*0c0b2b49SDavid du Colombier * which calls shutdown(0) and idles non-bootstrap cpus and returns
636*0c0b2b49SDavid du Colombier * on bootstrap processors (to permit a reboot). clearing our bit
637*0c0b2b49SDavid du Colombier * in machs avoids calling exit(0) from hzclock() on this processor.
638*0c0b2b49SDavid du Colombier */
639*0c0b2b49SDavid du Colombier active.machs &= ~(1<<m->machno);
640*0c0b2b49SDavid du Colombier active.exiting = 1;
641*0c0b2b49SDavid du Colombier iunlock(&active);
642*0c0b2b49SDavid du Colombier
643*0c0b2b49SDavid du Colombier if(once) {
644*0c0b2b49SDavid du Colombier delay(m->machno*1000); /* stagger them */
645*0c0b2b49SDavid du Colombier iprint("cpu%d: exiting\n", m->machno);
646*0c0b2b49SDavid du Colombier }
647*0c0b2b49SDavid du Colombier spllo();
648*0c0b2b49SDavid du Colombier for(ms = MAXMACH * 1000; ms > 0; ms -= TK2MS(2)){
649*0c0b2b49SDavid du Colombier delay(TK2MS(2));
650*0c0b2b49SDavid du Colombier if(active.machs == 0 && consactive() == 0)
651*0c0b2b49SDavid du Colombier break;
652*0c0b2b49SDavid du Colombier }
653*0c0b2b49SDavid du Colombier delay(100);
654*0c0b2b49SDavid du Colombier }
655*0c0b2b49SDavid du Colombier
656*0c0b2b49SDavid du Colombier void
exit(int ispanic)657*0c0b2b49SDavid du Colombier exit(int ispanic)
658*0c0b2b49SDavid du Colombier {
659*0c0b2b49SDavid du Colombier int timer;
660*0c0b2b49SDavid du Colombier
661*0c0b2b49SDavid du Colombier delay(1000);
662*0c0b2b49SDavid du Colombier shutdown(ispanic);
663*0c0b2b49SDavid du Colombier timer = 0;
664*0c0b2b49SDavid du Colombier while(active.machs || consactive()) {
665*0c0b2b49SDavid du Colombier if(timer++ > 400)
666*0c0b2b49SDavid du Colombier break;
667*0c0b2b49SDavid du Colombier delay(10);
668*0c0b2b49SDavid du Colombier }
669*0c0b2b49SDavid du Colombier delay(1000);
670*0c0b2b49SDavid du Colombier splhi();
671*0c0b2b49SDavid du Colombier
672*0c0b2b49SDavid du Colombier setstatus(BEV);
673*0c0b2b49SDavid du Colombier coherence();
674*0c0b2b49SDavid du Colombier
675*0c0b2b49SDavid du Colombier iprint("exit: awaiting reset\n");
676*0c0b2b49SDavid du Colombier delay(1000); /* await a reset */
677*0c0b2b49SDavid du Colombier
678*0c0b2b49SDavid du Colombier if(!active.ispanic) {
679*0c0b2b49SDavid du Colombier iprint("exit: jumping to rom\n");
680*0c0b2b49SDavid du Colombier *Reset |= Rstcpucold; /* cpu cold reset */
681*0c0b2b49SDavid du Colombier }
682*0c0b2b49SDavid du Colombier
683*0c0b2b49SDavid du Colombier iprint("exit: looping\n");
684*0c0b2b49SDavid du Colombier for(;;);
685*0c0b2b49SDavid du Colombier }
686*0c0b2b49SDavid du Colombier
687*0c0b2b49SDavid du Colombier /*
688*0c0b2b49SDavid du Colombier * the new kernel is already loaded at address `code'
689*0c0b2b49SDavid du Colombier * of size `size' and entry point `entry'.
690*0c0b2b49SDavid du Colombier */
691*0c0b2b49SDavid du Colombier void
reboot(void * entry,void * code,ulong size)692*0c0b2b49SDavid du Colombier reboot(void *entry, void *code, ulong size)
693*0c0b2b49SDavid du Colombier {
694*0c0b2b49SDavid du Colombier void (*f)(ulong, ulong, ulong, ulong);
695*0c0b2b49SDavid du Colombier
696*0c0b2b49SDavid du Colombier writeconf();
697*0c0b2b49SDavid du Colombier
698*0c0b2b49SDavid du Colombier /*
699*0c0b2b49SDavid du Colombier * the boot processor is cpu0. execute this function on it
700*0c0b2b49SDavid du Colombier * so that the new kernel has the same cpu0.
701*0c0b2b49SDavid du Colombier */
702*0c0b2b49SDavid du Colombier if(m->machno != 0) {
703*0c0b2b49SDavid du Colombier procwired(up, 0);
704*0c0b2b49SDavid du Colombier sched();
705*0c0b2b49SDavid du Colombier }
706*0c0b2b49SDavid du Colombier if(m->machno != 0)
707*0c0b2b49SDavid du Colombier print("on cpu%d (not 0)!\n", m->machno);
708*0c0b2b49SDavid du Colombier
709*0c0b2b49SDavid du Colombier if(code == nil || entry == nil)
710*0c0b2b49SDavid du Colombier exit(1);
711*0c0b2b49SDavid du Colombier
712*0c0b2b49SDavid du Colombier shutdown(0);
713*0c0b2b49SDavid du Colombier
714*0c0b2b49SDavid du Colombier /*
715*0c0b2b49SDavid du Colombier * should be the only processor running now
716*0c0b2b49SDavid du Colombier */
717*0c0b2b49SDavid du Colombier iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
718*0c0b2b49SDavid du Colombier iprint("code[0] = %#lux\n", *(ulong *)code);
719*0c0b2b49SDavid du Colombier
720*0c0b2b49SDavid du Colombier /* turn off buffered serial console */
721*0c0b2b49SDavid du Colombier serialoq = nil;
722*0c0b2b49SDavid du Colombier kprintoq = nil;
723*0c0b2b49SDavid du Colombier screenputs = nil;
724*0c0b2b49SDavid du Colombier
725*0c0b2b49SDavid du Colombier /* shutdown devices */
726*0c0b2b49SDavid du Colombier chandevshutdown();
727*0c0b2b49SDavid du Colombier
728*0c0b2b49SDavid du Colombier splhi();
729*0c0b2b49SDavid du Colombier intrshutdown();
730*0c0b2b49SDavid du Colombier
731*0c0b2b49SDavid du Colombier /* setup reboot trampoline function */
732*0c0b2b49SDavid du Colombier f = (void*)REBOOTADDR;
733*0c0b2b49SDavid du Colombier // memmove(f, rebootcode, sizeof(rebootcode));
734*0c0b2b49SDavid du Colombier // icflush(f, sizeof(rebootcode));
735*0c0b2b49SDavid du Colombier
736*0c0b2b49SDavid du Colombier setstatus(BEV); /* also, kernel mode, no interrupts */
737*0c0b2b49SDavid du Colombier coherence();
738*0c0b2b49SDavid du Colombier
739*0c0b2b49SDavid du Colombier /* off we go - never to return */
740*0c0b2b49SDavid du Colombier (*f)((ulong)entry, (ulong)code, size, _argc);
741*0c0b2b49SDavid du Colombier
742*0c0b2b49SDavid du Colombier panic("loaded kernel returned!");
743*0c0b2b49SDavid du Colombier }
744*0c0b2b49SDavid du Colombier
745*0c0b2b49SDavid du Colombier /*
746*0c0b2b49SDavid du Colombier * stub for ../port/devpnp.c
747*0c0b2b49SDavid du Colombier */
748*0c0b2b49SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)749*0c0b2b49SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
750*0c0b2b49SDavid du Colombier {
751*0c0b2b49SDavid du Colombier USED(class, ctlrno, isa);
752*0c0b2b49SDavid du Colombier return 0;
753*0c0b2b49SDavid du Colombier }
754