1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department, The Mach Operating System project at
9  * Carnegie-Mellon University, Ralph Campbell, Sony Corp. and Kazumasa
10  * Utashiro of Software Research Associates, Inc.
11  *
12  * %sccs.include.redist.c%
13  *
14  *	@(#)machdep.c	7.9 (Berkeley) 03/10/93
15  */
16 
17 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/signalvar.h>
22 #include <sys/kernel.h>
23 #include <sys/map.h>
24 #include <sys/proc.h>
25 #include <sys/buf.h>
26 #include <sys/reboot.h>
27 #include <sys/conf.h>
28 #include <sys/file.h>
29 #include <sys/clist.h>
30 #include <sys/callout.h>
31 #include <sys/malloc.h>
32 #include <sys/mbuf.h>
33 #include <sys/msgbuf.h>
34 #include <sys/user.h>
35 #include <sys/exec.h>
36 #ifdef SYSVSHM
37 #include <sys/shm.h>
38 #endif
39 
40 #include <vm/vm.h>
41 #include <vm/vm_kern.h>
42 #include <vm/vm_page.h>
43 
44 #include <machine/cpu.h>
45 #include <machine/reg.h>
46 #include <machine/psl.h>
47 #include <machine/pte.h>
48 
49 #include <machine/adrsmap.h>
50 
51 vm_map_t buffer_map;
52 
53 /* the following is used externally (sysctl_hw) */
54 char	machine[] = "SONY";	/* cpu "architecture" */
55 char	cpu_model[30];
56 
57 /*
58  * Declare these as initialized data so we can patch them.
59  */
60 int	nswbuf = 0;
61 #ifdef	NBUF
62 int	nbuf = NBUF;
63 #else
64 int	nbuf = 0;
65 #endif
66 #ifdef	BUFPAGES
67 int	bufpages = BUFPAGES;
68 #else
69 int	bufpages = 0;
70 #endif
71 int	msgbufmapped = 0;	/* set when safe to use msgbuf */
72 int	maxmem;			/* max memory per process */
73 int	physmem;		/* max supported memory, changes to actual */
74 /*
75  * safepri is a safe priority for sleep to set for a spin-wait
76  * during autoconfiguration or after a panic.
77  */
78 int	safepri = PSL_LOWIPL;
79 
80 struct	user *proc0paddr;
81 struct	proc nullproc;		/* for use by swtch_exit() */
82 
83 /*
84  * Do all the stuff that locore normally does before calling main().
85  * Process arguments passed to us by the prom monitor.
86  * Return the first page address following the system.
87  */
88 mach_init(x_boothowto, x_unkown, x_bootdev, x_maxmem)
89 	int x_boothowto;
90 	int x_unkown;
91 	int x_bootdev;
92 	int x_maxmem;
93 {
94 	register char *cp;
95 	register int i;
96 	register unsigned firstaddr;
97 	register caddr_t v;
98 	caddr_t start;
99 	extern u_long bootdev;
100 	extern char edata[], end[];
101 	extern char MachUTLBMiss[], MachUTLBMissEnd[];
102 	extern char MachException[], MachExceptionEnd[];
103 #ifdef ATTR
104 	extern char *pmap_attributes;
105 #endif
106 
107 	/*
108 	 * Save parameters into kernel work area.
109 	 */
110 	*(int *)(MACH_CACHED_TO_UNCACHED(MACH_MAXMEMSIZE_ADDR)) = x_maxmem;
111 	*(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTDEV_ADDR)) = x_bootdev;
112 	*(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTSW_ADDR)) = x_boothowto;
113 
114 	/* clear the BSS segment */
115 	v = (caddr_t)pmax_round_page(end);
116 	bzero(edata, v - edata);
117 
118 	boothowto = x_boothowto;
119 	bootdev = x_bootdev;
120 	maxmem = physmem = pmax_btop(x_maxmem);
121 
122 	/*
123 	 * Look at arguments passed to us and compute boothowto.
124 	 */
125 #ifdef GENERIC
126 	boothowto |= RB_SINGLE | RB_ASKNAME;
127 #endif
128 #ifdef KADB
129 	boothowto |= RB_KDB;
130 #endif
131 
132 #ifdef MFS
133 	/*
134 	 * Check to see if a mini-root was loaded into memory. It resides
135 	 * at the start of the next page just after the end of BSS.
136 	 */
137 	if (boothowto & RB_MINIROOT) {
138 		boothowto |= RB_DFLTROOT;
139 		v += mfs_initminiroot(v);
140 	}
141 #endif
142 
143 	/*
144 	 * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
145 	 */
146 	start = v;
147 	curproc->p_addr = proc0paddr = (struct user *)v;
148 	curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
149 	firstaddr = MACH_CACHED_TO_PHYS(v);
150 	for (i = 0; i < UPAGES; i++) {
151 		MachTLBWriteIndexed(i,
152 			(UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT),
153 			curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M);
154 		firstaddr += NBPG;
155 	}
156 	v += UPAGES * NBPG;
157 	MachSetPID(1);
158 
159 	/*
160 	 * init nullproc for swtch_exit().
161 	 * init mapping for u page(s), pm_tlbpid 0
162 	 * This could be used for an idle process.
163 	 */
164 	nullproc.p_addr = (struct user *)v;
165 	nullproc.p_md.md_regs = ((struct user *)v)->u_pcb.pcb_regs;
166 	for (i = 0; i < UPAGES; i++) {
167 		nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M;
168 		firstaddr += NBPG;
169 	}
170 	v += UPAGES * NBPG;
171 
172 	/* clear pages for u areas */
173 	bzero(start, v - start);
174 
175 	/*
176 	 * Copy down exception vector code.
177 	 */
178 	if (MachUTLBMissEnd - MachUTLBMiss > 0x80)
179 		panic("startup: UTLB code too large");
180 	bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC,
181 		MachUTLBMissEnd - MachUTLBMiss);
182 	bcopy(MachException, (char *)MACH_GEN_EXC_VEC,
183 		MachExceptionEnd - MachException);
184 
185 	/*
186 	 * Clear out the I and D caches.
187 	 */
188 	MachConfigCache();
189 	MachFlushCache();
190 
191 	/*
192 	 * Initialize error message buffer (at end of core).
193 	 */
194 	maxmem -= btoc(sizeof (struct msgbuf));
195 	msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT));
196 	msgbufmapped = 1;
197 
198 	/*
199 	 * Allocate space for system data structures.
200 	 * The first available kernel virtual address is in "v".
201 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
202 	 *
203 	 * These data structures are allocated here instead of cpu_startup()
204 	 * because physical memory is directly addressable. We don't have
205 	 * to map these into virtual address space.
206 	 */
207 	start = v;
208 
209 #define	valloc(name, type, num) \
210 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
211 #define	valloclim(name, type, num, lim) \
212 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
213 	valloc(cfree, struct cblock, nclist);
214 	valloc(callout, struct callout, ncallout);
215 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
216 #ifdef SYSVSHM
217 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
218 #endif
219 #ifdef ATTR
220 	/* this is allocated here just to save a few bytes */
221 	valloc(pmap_attributes, char, physmem);
222 #endif
223 
224 	/*
225 	 * Determine how many buffers to allocate.
226 	 * We allocate more buffer space than the BSD standard of
227 	 * using 10% of memory for the first 2 Meg, 5% of remaining.
228 	 * We just allocate a flat 10%.  Insure a minimum of 16 buffers.
229 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
230 	 */
231 	if (bufpages == 0)
232 		bufpages = physmem / 10 / CLSIZE;
233 	if (nbuf == 0) {
234 		nbuf = bufpages;
235 		if (nbuf < 16)
236 			nbuf = 16;
237 	}
238 	if (nswbuf == 0) {
239 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
240 		if (nswbuf > 256)
241 			nswbuf = 256;		/* sanity */
242 	}
243 	valloc(swbuf, struct buf, nswbuf);
244 	valloc(buf, struct buf, nbuf);
245 
246 	/*
247 	 * Clear allocated memory.
248 	 */
249 	v = (caddr_t)pmax_round_page(v);
250 	bzero(start, v - start);
251 
252 	/*
253 	 * Initialize the virtual memory system.
254 	 */
255 	pmap_bootstrap((vm_offset_t)MACH_CACHED_TO_PHYS(v));
256 }
257 
258 /*
259  * Console initialization: called early on from main,
260  * before vm init or startup.  Do enough configuration
261  * to choose and initialize a console.
262  * XXX need something better here.
263  */
264 #define	SCC_CONSOLE	0
265 #define	SW_CONSOLE	0x07
266 #define	SW_NWB512	0x04
267 #define	SW_NWB225	0x01
268 #define	SW_FBPOP	0x02
269 #define	SW_FBPOP1	0x06
270 #define	SW_FBPOP2	0x03
271 #define	SW_AUTOSEL	0x07
272 consinit()
273 {
274 	extern dev_t consdev;
275 	extern struct tty *constty, *cn_tty, *rs_tty;
276 	int dipsw = (int)*(volatile u_char *)DIP_SWITCH;
277 
278 #include "bm.h"
279 #if NBM > 0
280 #if defined(news3200) || defined(news3400)	/* KU:XXX */
281 	fbbm_probe(dipsw|2);
282 #else
283 	fbbm_probe(dipsw);
284 #endif
285 	vt100_open();
286 	setup_fnt();
287 	setup_fnt24();
288 #else
289 	dipsw &= SW_CONSOLE;
290 #endif
291 
292 	switch (dipsw & SW_CONSOLE) {
293 	    case 0:
294 		scc_open(SCC_CONSOLE);
295 		consdev = makedev(1, 0);
296 		constty = rs_tty;
297 		break;
298 
299 	    default:
300 #if NBM > 0
301 		consdev = makedev(22, 0);
302 		constty = cn_tty;
303 #endif
304 		break;
305 	}
306 	return(0);
307 }
308 
309 /*
310  * cpu_startup: allocate memory for variable-sized tables,
311  * initialize cpu, and do autoconfiguration.
312  */
313 cpu_startup()
314 {
315 	register unsigned i;
316 	register caddr_t v;
317 	int base, residual;
318 	extern long Usrptsize;
319 	extern struct map *useriomap;
320 #ifdef DEBUG
321 	extern int pmapdebug;
322 	int opmapdebug = pmapdebug;
323 #endif
324 	vm_offset_t minaddr, maxaddr;
325 	vm_size_t size;
326 
327 #ifdef DEBUG
328 	pmapdebug = 0;
329 #endif
330 
331 	/*
332 	 * Good {morning,afternoon,evening,night}.
333 	 */
334 	printf(version);
335 	printf("real mem = %d\n", ctob(physmem));
336 
337 	/*
338 	 * Allocate virtual address space for file I/O buffers.
339 	 * Note they are different than the array of headers, 'buf',
340 	 * and usually occupy more virtual memory than physical.
341 	 */
342 	size = MAXBSIZE * nbuf;
343 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
344 				   &maxaddr, size, FALSE);
345 	minaddr = (vm_offset_t)buffers;
346 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
347 			&minaddr, size, FALSE) != KERN_SUCCESS)
348 		panic("startup: cannot allocate buffers");
349 	base = bufpages / nbuf;
350 	residual = bufpages % nbuf;
351 	for (i = 0; i < nbuf; i++) {
352 		vm_size_t curbufsize;
353 		vm_offset_t curbuf;
354 
355 		/*
356 		 * First <residual> buffers get (base+1) physical pages
357 		 * allocated for them.  The rest get (base) physical pages.
358 		 *
359 		 * The rest of each buffer occupies virtual space,
360 		 * but has no physical memory allocated for it.
361 		 */
362 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
363 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
364 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
365 		vm_map_simplify(buffer_map, curbuf);
366 	}
367 	/*
368 	 * Allocate a submap for exec arguments.  This map effectively
369 	 * limits the number of processes exec'ing at any time.
370 	 */
371 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
372 				 16*NCARGS, TRUE);
373 	/*
374 	 * Allocate a submap for physio
375 	 */
376 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
377 				 VM_PHYS_SIZE, TRUE);
378 
379 	/*
380 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
381 	 * we use the more space efficient malloc in place of kmem_alloc.
382 	 */
383 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
384 				   M_MBUF, M_NOWAIT);
385 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
386 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
387 			       VM_MBUF_SIZE, FALSE);
388 	/*
389 	 * Initialize callouts
390 	 */
391 	callfree = callout;
392 	for (i = 1; i < ncallout; i++)
393 		callout[i-1].c_next = &callout[i];
394 	callout[i-1].c_next = NULL;
395 
396 #ifdef DEBUG
397 	pmapdebug = opmapdebug;
398 #endif
399 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
400 	printf("using %d buffers containing %d bytes of memory\n",
401 		nbuf, bufpages * CLBYTES);
402 	/*
403 	 * Set up CPU-specific registers, cache, etc.
404 	 */
405 	initcpu();
406 
407 	/*
408 	 * Set up buffers, so they can be used to read disk labels.
409 	 */
410 	bufinit();
411 
412 	/*
413 	 * Configure the system.
414 	 */
415 	configure();
416 }
417 
418 /*
419  * Set registers on exec.
420  * Clear all registers except sp, pc.
421  */
422 setregs(p, entry, retval)
423 	register struct proc *p;
424 	u_long entry;
425 	int retval[2];
426 {
427 	int sp = p->p_md.md_regs[SP];
428 	extern struct proc *machFPCurProcPtr;
429 
430 	bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
431 	p->p_md.md_regs[SP] = sp;
432 	p->p_md.md_regs[PC] = entry & ~3;
433 	p->p_md.md_regs[PS] = PSL_USERSET;
434 	p->p_md.md_flags & ~MDP_FPUSED;
435 	if (machFPCurProcPtr == p)
436 		machFPCurProcPtr = (struct proc *)0;
437 }
438 
439 /*
440  * WARNING: code in locore.s assumes the layout shown for sf_signum
441  * thru sf_handler so... don't screw with them!
442  */
443 struct sigframe {
444 	int	sf_signum;		/* signo for handler */
445 	int	sf_code;		/* additional info for handler */
446 	struct	sigcontext *sf_scp;	/* context ptr for handler */
447 	sig_t	sf_handler;		/* handler addr for u_sigc */
448 	struct	sigcontext sf_sc;	/* actual context */
449 };
450 
451 #ifdef DEBUG
452 int sigdebug = 0;
453 int sigpid = 0;
454 #define SDB_FOLLOW	0x01
455 #define SDB_KSTACK	0x02
456 #define SDB_FPSTATE	0x04
457 #endif
458 
459 /*
460  * Send an interrupt to process.
461  */
462 void
463 sendsig(catcher, sig, mask, code)
464 	sig_t catcher;
465 	int sig, mask;
466 	unsigned code;
467 {
468 	register struct proc *p = curproc;
469 	register struct sigframe *fp;
470 	register int *regs;
471 	register struct sigacts *psp = p->p_sigacts;
472 	int oonstack, fsize;
473 	struct sigcontext ksc;
474 	extern char sigcode[], esigcode[];
475 
476 	regs = p->p_md.md_regs;
477 	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
478 	/*
479 	 * Allocate and validate space for the signal handler
480 	 * context. Note that if the stack is in data space, the
481 	 * call to grow() is a nop, and the copyout()
482 	 * will fail if the process has not already allocated
483 	 * the space with a `brk'.
484 	 */
485 	fsize = sizeof(struct sigframe);
486 	if ((psp->ps_flags & SAS_ALTSTACK) &&
487 	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
488 	    (psp->ps_sigonstack & sigmask(sig))) {
489 		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
490 					 psp->ps_sigstk.ss_size - fsize);
491 		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
492 	} else
493 		fp = (struct sigframe *)(regs[SP] - fsize);
494 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
495 		(void)grow(p, (unsigned)fp);
496 #ifdef DEBUG
497 	if ((sigdebug & SDB_FOLLOW) ||
498 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
499 		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
500 		       p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
501 #endif
502 	/*
503 	 * Build the signal context to be used by sigreturn.
504 	 */
505 	ksc.sc_onstack = oonstack;
506 	ksc.sc_mask = mask;
507 	ksc.sc_pc = regs[PC];
508 	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */
509 	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
510 		sizeof(ksc.sc_regs) - sizeof(int));
511 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
512 	if (ksc.sc_fpused) {
513 		extern struct proc *machFPCurProcPtr;
514 
515 		/* if FPU has current state, save it first */
516 		if (p == machFPCurProcPtr)
517 			MachSaveCurFPState(p);
518 		bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
519 			sizeof(ksc.sc_fpregs));
520 	}
521 	if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
522 		/*
523 		 * Process has trashed its stack; give it an illegal
524 		 * instruction to halt it in its tracks.
525 		 */
526 		SIGACTION(p, SIGILL) = SIG_DFL;
527 		sig = sigmask(SIGILL);
528 		p->p_sigignore &= ~sig;
529 		p->p_sigcatch &= ~sig;
530 		p->p_sigmask &= ~sig;
531 		psignal(p, SIGILL);
532 		return;
533 	}
534 	/*
535 	 * Build the argument list for the signal handler.
536 	 */
537 	regs[A0] = sig;
538 	regs[A1] = code;
539 	regs[A2] = (int)&fp->sf_sc;
540 	regs[A3] = (int)catcher;
541 
542 	regs[PC] = (int)catcher;
543 	regs[SP] = (int)fp;
544 	/*
545 	 * Signal trampoline code is at base of user stack.
546 	 */
547 	regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
548 #ifdef DEBUG
549 	if ((sigdebug & SDB_FOLLOW) ||
550 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
551 		printf("sendsig(%d): sig %d returns\n",
552 		       p->p_pid, sig);
553 #endif
554 }
555 
556 /*
557  * System call to cleanup state after a signal
558  * has been taken.  Reset signal mask and
559  * stack state from context left by sendsig (above).
560  * Return to previous pc and psl as specified by
561  * context left by sendsig. Check carefully to
562  * make sure that the user has not modified the
563  * psl to gain improper priviledges or to cause
564  * a machine fault.
565  */
566 struct sigreturn_args {
567 	struct sigcontext *sigcntxp;
568 };
569 /* ARGSUSED */
570 sigreturn(p, uap, retval)
571 	struct proc *p;
572 	struct sigreturn_args *uap;
573 	int *retval;
574 {
575 	register struct sigcontext *scp;
576 	register int *regs;
577 	struct sigcontext ksc;
578 	int error;
579 
580 	scp = uap->sigcntxp;
581 #ifdef DEBUG
582 	if (sigdebug & SDB_FOLLOW)
583 		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
584 #endif
585 	regs = p->p_md.md_regs;
586 	/*
587 	 * Test and fetch the context structure.
588 	 * We grab it all at once for speed.
589 	 */
590 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
591 	if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
592 #ifdef DEBUG
593 		if (!(sigdebug & SDB_FOLLOW))
594 			printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
595 		printf("  old sp %x ra %x pc %x\n",
596 			regs[SP], regs[RA], regs[PC]);
597 		printf("  new sp %x ra %x pc %x err %d z %x\n",
598 			ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
599 			error, ksc.sc_regs[ZERO]);
600 #endif
601 		return (EINVAL);
602 	}
603 	scp = &ksc;
604 	/*
605 	 * Restore the user supplied information
606 	 */
607 	if (scp->sc_onstack & 01)
608 		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
609 	else
610 		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
611 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
612 	regs[PC] = scp->sc_pc;
613 	bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)&regs[1],
614 		sizeof(scp->sc_regs) - sizeof(int));
615 	if (scp->sc_fpused)
616 		bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
617 			sizeof(scp->sc_fpregs));
618 	return (EJUSTRETURN);
619 }
620 
621 int	waittime = -1;
622 
623 boot(howto)
624 	register int howto;
625 {
626 
627 	/* take a snap shot before clobbering any registers */
628 	if (curproc)
629 		savectx(curproc->p_addr, 0);
630 
631 	boothowto = howto;
632 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
633 		register struct buf *bp;
634 		int iter, nbusy;
635 
636 		waittime = 0;
637 		(void) spl0();
638 		printf("syncing disks... ");
639 		/*
640 		 * Release vnodes held by texts before sync.
641 		 */
642 		if (panicstr == 0)
643 			vnode_pager_umount(NULL);
644 #ifdef notyet
645 #include "fd.h"
646 #if NFD > 0
647 		fdshutdown();
648 #endif
649 #endif
650 		sync(&proc0, (void *)NULL, (int *)NULL);
651 
652 		for (iter = 0; iter < 20; iter++) {
653 			nbusy = 0;
654 			for (bp = &buf[nbuf]; --bp >= buf; )
655 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
656 					nbusy++;
657 			if (nbusy == 0)
658 				break;
659 			printf("%d ", nbusy);
660 			DELAY(40000 * iter);
661 		}
662 		if (nbusy)
663 			printf("giving up\n");
664 		else
665 			printf("done\n");
666 		/*
667 		 * If we've been adjusting the clock, the todr
668 		 * will be out of synch; adjust it now.
669 		 */
670 		resettodr();
671 	}
672 	(void) splhigh();		/* extreme priority */
673 	if (howto & RB_HALT) {
674 		halt(howto);
675 		/*NOTREACHED*/
676 	} else {
677 		if (howto & RB_DUMP)
678 			dumpsys();
679 		halt(howto);
680 		/*NOTREACHED*/
681 	}
682 	/*NOTREACHED*/
683 }
684 
685 halt(howto)
686 	int howto;
687 {
688 	if (*(volatile u_char *)DIP_SWITCH & 0x20)
689 		howto |= RB_HALT;
690 	to_monitor(howto);
691 	/*NOTREACHED*/
692 }
693 
694 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
695 int	dumpsize = 0;		/* also for savecore */
696 long	dumplo = 0;
697 
698 dumpconf()
699 {
700 	int nblks;
701 
702 	dumpsize = physmem;
703 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
704 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
705 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
706 			dumpsize = btoc(dbtob(nblks - dumplo));
707 		else if (dumplo == 0)
708 			dumplo = nblks - btodb(ctob(physmem));
709 	}
710 	/*
711 	 * Don't dump on the first CLBYTES (why CLBYTES?)
712 	 * in case the dump device includes a disk label.
713 	 */
714 	if (dumplo < btodb(CLBYTES))
715 		dumplo = btodb(CLBYTES);
716 }
717 
718 /*
719  * Doadump comes here after turning off memory management and
720  * getting on the dump stack, either when called above, or by
721  * the auto-restart code.
722  */
723 dumpsys()
724 {
725 	int error;
726 
727 	msgbufmapped = 0;
728 	if (dumpdev == NODEV)
729 		return;
730 	/*
731 	 * For dumps during autoconfiguration,
732 	 * if dump device has already configured...
733 	 */
734 	if (dumpsize == 0)
735 		dumpconf();
736 	if (dumplo < 0)
737 		return;
738 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
739 	printf("dump ");
740 	switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
741 
742 	case ENXIO:
743 		printf("device bad\n");
744 		break;
745 
746 	case EFAULT:
747 		printf("device not ready\n");
748 		break;
749 
750 	case EINVAL:
751 		printf("area improper\n");
752 		break;
753 
754 	case EIO:
755 		printf("i/o error\n");
756 		break;
757 
758 	default:
759 		printf("error %d\n", error);
760 		break;
761 
762 	case 0:
763 		printf("succeeded\n");
764 	}
765 }
766 
767 /*
768  * Return the best possible estimate of the time in the timeval
769  * to which tvp points.  Unfortunately, we can't read the hardware registers.
770  * We guarantee that the time will be greater than the value obtained by a
771  * previous call.
772  */
773 microtime(tvp)
774 	register struct timeval *tvp;
775 {
776 	int s = splclock();
777 	static struct timeval lasttime;
778 
779 	*tvp = time;
780 #ifdef notdef
781 	tvp->tv_usec += clkread();
782 	while (tvp->tv_usec > 1000000) {
783 		tvp->tv_sec++;
784 		tvp->tv_usec -= 1000000;
785 	}
786 #endif
787 	if (tvp->tv_sec == lasttime.tv_sec &&
788 	    tvp->tv_usec <= lasttime.tv_usec &&
789 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
790 		tvp->tv_sec++;
791 		tvp->tv_usec -= 1000000;
792 	}
793 	lasttime = *tvp;
794 	splx(s);
795 }
796 
797 initcpu()
798 {
799 
800 	/*
801 	 * clear LEDs
802 	 */
803 	*(char*)DEBUG_PORT = (char)DP_WRITE|DP_LED0|DP_LED1|DP_LED2|DP_LED3;
804 
805 	/*
806 	 * clear all interrupts
807 	 */
808 	*(char*)INTCLR0 = 0;
809 	*(char*)INTCLR1 = 0;
810 
811 	/*
812 	 * It's not a time to enable timer yet.
813 	 *
814 	 *	INTEN0:  PERR ABORT BERR TIMER KBD  MS    CFLT CBSY
815 	 *		  o     o    o     x    o    o     x    x
816 	 *	INTEN1:  BEEP SCC  LANCE DMA  SLOT1 SLOT3 EXT1 EXT3
817 	 *		  x     o    o     o    o    o     x    x
818 	 */
819 
820 	*(char*)INTEN0 = (char) INTEN0_PERR|INTEN0_ABORT|INTEN0_BERR|
821 				INTEN0_KBDINT|INTEN0_MSINT;
822 
823 	*(char*)INTEN1 = (char) INTEN1_SCC|INTEN1_LANCE|INTEN1_DMA|
824 				INTEN1_SLOT1|INTEN1_SLOT3;
825 
826 	spl0();		/* safe to turn interrupts on now */
827 }
828 
829 /*
830  * Convert an ASCII string into an integer.
831  */
832 int
833 atoi(s)
834 	char *s;
835 {
836 	int c;
837 	unsigned base = 10, d;
838 	int neg = 0, val = 0;
839 
840 	if (s == 0 || (c = *s++) == 0)
841 		goto out;
842 
843 	/* skip spaces if any */
844 	while (c == ' ' || c == '\t')
845 		c = *s++;
846 
847 	/* parse sign, allow more than one (compat) */
848 	while (c == '-') {
849 		neg = !neg;
850 		c = *s++;
851 	}
852 
853 	/* parse base specification, if any */
854 	if (c == '0') {
855 		c = *s++;
856 		switch (c) {
857 		case 'X':
858 		case 'x':
859 			base = 16;
860 			break;
861 		case 'B':
862 		case 'b':
863 			base = 2;
864 			break;
865 		default:
866 			base = 8;
867 			break;
868 		}
869 	}
870 
871 	/* parse number proper */
872 	for (;;) {
873 		if (c >= '0' && c <= '9')
874 			d = c - '0';
875 		else if (c >= 'a' && c <= 'z')
876 			d = c - 'a' + 10;
877 		else if (c >= 'A' && c <= 'Z')
878 			d = c - 'A' + 10;
879 		else
880 			break;
881 		val *= base;
882 		val += d;
883 		c = *s++;
884 	}
885 	if (neg)
886 		val = -val;
887 out:
888 	return val;
889 }
890 
891 #ifdef CPU_SINGLE
892 /*
893  * small ring buffers for keyboard/mouse
894  */
895 struct ring_buf {
896 	u_char head;
897 	u_char tail;
898 	u_char count;
899 	u_char buf[13];
900 } ring_buf[2];
901 
902 xputc(c, chan)
903 	u_char c;
904 	int chan;
905 {
906 	register struct ring_buf *p = &ring_buf[chan];
907 	int s = splhigh();
908 
909 	if (p->count >= sizeof (p->buf)) {
910 		(void) splx(s);
911 		return (-1);
912 	}
913 	p->buf[p->head] = c;
914 	if (++p->head >= sizeof (p->buf))
915 		p->head = 0;
916 	p->count++;
917 	(void) splx(s);
918 	return (c);
919 }
920 
921 xgetc(chan)
922 	int chan;
923 {
924 	register struct ring_buf *p = &ring_buf[chan];
925 	int c;
926 	int s = splhigh();
927 
928 	if (p->count == 0) {
929 		(void) splx(s);
930 		return (-1);
931 	}
932 	c = p->buf[p->tail];
933 	if (++p->tail >= sizeof (p->buf))
934 		p->tail = 0;
935 	p->count--;
936 	(void) splx(s);
937 	return (c);
938 }
939 #endif /* CPU_SINGLE */
940