xref: /original-bsd/sys/pmax/pmax/machdep.c (revision 3b3772fe)
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 and Ralph Campbell.
10  *
11  * %sccs.include.redist.c%
12  *
13  *	@(#)machdep.c	7.11 (Berkeley) 10/24/92
14  */
15 
16 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/signalvar.h>
21 #include <sys/kernel.h>
22 #include <sys/map.h>
23 #include <sys/proc.h>
24 #include <sys/buf.h>
25 #include <sys/reboot.h>
26 #include <sys/conf.h>
27 #include <sys/file.h>
28 #include <sys/clist.h>
29 #include <sys/callout.h>
30 #include <sys/malloc.h>
31 #include <sys/mbuf.h>
32 #include <sys/msgbuf.h>
33 #include <sys/user.h>
34 #include <sys/exec.h>
35 #ifdef SYSVSHM
36 #include <sys/shm.h>
37 #endif
38 
39 #include <vm/vm.h>
40 #include <vm/vm_kern.h>
41 #include <vm/vm_page.h>
42 
43 #include <machine/cpu.h>
44 #include <machine/reg.h>
45 #include <machine/psl.h>
46 #include <machine/machMon.h>
47 #include <machine/pte.h>
48 
49 #include <pmax/dev/device.h>
50 
51 #include <pmax/pmax/clockreg.h>
52 
53 vm_map_t buffer_map;
54 
55 /*
56  * Declare these as initialized data so we can patch them.
57  */
58 int	nswbuf = 0;
59 #ifdef	NBUF
60 int	nbuf = NBUF;
61 #else
62 int	nbuf = 0;
63 #endif
64 #ifdef	BUFPAGES
65 int	bufpages = BUFPAGES;
66 #else
67 int	bufpages = 0;
68 #endif
69 int	msgbufmapped;		/* set when safe to use msgbuf */
70 int	maxmem;			/* max memory per process */
71 int	physmem;		/* max supported memory, changes to actual */
72 /*
73  * safepri is a safe priority for sleep to set for a spin-wait
74  * during autoconfiguration or after a panic.
75  */
76 int	safepri = PSL_LOWIPL;
77 
78 struct	user *proc0paddr;
79 struct	proc nullproc;		/* for use by swtch_exit() */
80 
81 /*
82  * Do all the stuff that locore normally does before calling main().
83  * Process arguments passed to us by the prom monitor.
84  * Return the first page address following the system.
85  */
86 mach_init(argc, argv)
87 	int argc;
88 	char *argv[];
89 {
90 	register char *cp;
91 	register int i;
92 	register unsigned firstaddr;
93 	register caddr_t v;
94 	caddr_t start;
95 	extern char edata[], end[];
96 	extern char MachUTLBMiss[], MachUTLBMissEnd[];
97 	extern char MachException[], MachExceptionEnd[];
98 #ifdef ATTR
99 	extern char *pmap_attributes;
100 #endif
101 
102 	/* clear the BSS segment */
103 	v = (caddr_t)pmax_round_page(end);
104 	bzero(edata, v - edata);
105 
106 #ifdef DS5000
107 	/* check for direct boot from DS5000 PROM */
108 	if (argc > 0 && strcmp(argv[0], "boot") == 0) {
109 		argc--;
110 		argv++;
111 	}
112 #endif
113 
114 	/* look at argv[0] and compute bootdev */
115 	makebootdev(argv[0]);
116 
117 	/*
118 	 * Look at arguments passed to us and compute boothowto.
119 	 */
120 #ifdef GENERIC
121 	boothowto = RB_SINGLE | RB_ASKNAME;
122 #else
123 	boothowto = RB_SINGLE;
124 #endif
125 #ifdef KADB
126 	boothowto |= RB_KDB;
127 #endif
128 	if (argc > 1) {
129 		for (i = 1; i < argc; i++) {
130 			for (cp = argv[i]; *cp; cp++) {
131 				switch (*cp) {
132 				case 'a': /* autoboot */
133 					boothowto &= ~RB_SINGLE;
134 					break;
135 
136 				case 'd': /* use compiled in default root */
137 					boothowto |= RB_DFLTROOT;
138 					break;
139 
140 				case 'm': /* mini root present in memory */
141 					boothowto |= RB_MINIROOT;
142 					break;
143 
144 				case 'n': /* ask for names */
145 					boothowto |= RB_ASKNAME;
146 					break;
147 
148 				case 'N': /* don't ask for names */
149 					boothowto &= ~RB_ASKNAME;
150 				}
151 			}
152 		}
153 	}
154 
155 #ifdef MFS
156 	/*
157 	 * Check to see if a mini-root was loaded into memory. It resides
158 	 * at the start of the next page just after the end of BSS.
159 	 */
160 	if (boothowto & RB_MINIROOT)
161 		v += mfs_initminiroot(v);
162 #endif
163 
164 	/*
165 	 * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
166 	 */
167 	start = v;
168 	curproc->p_addr = proc0paddr = (struct user *)v;
169 	curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
170 	firstaddr = MACH_CACHED_TO_PHYS(v);
171 	for (i = 0; i < UPAGES; i++) {
172 		MachTLBWriteIndexed(i,
173 			(UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT),
174 			curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M);
175 		firstaddr += NBPG;
176 	}
177 	v += UPAGES * NBPG;
178 	MachSetPID(1);
179 
180 	/*
181 	 * init nullproc for swtch_exit().
182 	 * init mapping for u page(s), pm_tlbpid 0
183 	 * This could be used for an idle process.
184 	 */
185 	nullproc.p_addr = (struct user *)v;
186 	nullproc.p_md.md_regs = ((struct user *)v)->u_pcb.pcb_regs;
187 	for (i = 0; i < UPAGES; i++) {
188 		nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M;
189 		firstaddr += NBPG;
190 	}
191 	v += UPAGES * NBPG;
192 
193 	/* clear pages for u areas */
194 	bzero(start, v - start);
195 
196 	/*
197 	 * Copy down exception vector code.
198 	 */
199 	if (MachUTLBMissEnd - MachUTLBMiss > 0x80)
200 		panic("startup: UTLB code too large");
201 	bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC,
202 		MachUTLBMissEnd - MachUTLBMiss);
203 	bcopy(MachException, (char *)MACH_GEN_EXC_VEC,
204 		MachExceptionEnd - MachException);
205 
206 	/*
207 	 * Clear out the I and D caches.
208 	 */
209 	MachConfigCache();
210 	MachFlushCache();
211 
212 	/*
213 	 * Determine what model of computer we are running on.
214 	 */
215 	{
216 		char *(*f)() = (char *(*)())MACH_MON_GETENV2;
217 
218 		if (cp = (*f)("systype"))
219 			i = atoi(cp);
220 		else
221 			cp = "";
222 
223 		/* check for MIPS based platform */
224 		if (((i >> 24) & 0xFF) != 0x82) {
225 			printf("Unknown System type '%s'\n", cp);
226 			boot(RB_HALT | RB_NOSYNC);
227 		}
228 	}
229 
230 	/* check what model platform we are running on */
231 	switch ((i >> 16) & 0xFF) {
232 #ifdef DS3100
233 	case 1:	/* DS3100 Pmax */
234 		/*
235 		 * Find out how much memory is available.
236 		 */
237 		physmem = btoc(v - KERNBASE);
238 		cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
239 		while (cp < (char *)MACH_MAX_MEM_ADDR) {
240 			if (badaddr(cp, 4))
241 				break;
242 			cp += NBPG;
243 			physmem++;
244 		}
245 		break;
246 #endif
247 
248 #ifdef DS5000
249 	case 2:	/* DS5000 3max */
250 	    {
251 		extern void tc_find_all_options();
252 
253 		/* disable all TURBOchannel interrupts */
254 		i = *(volatile int *)MACH_SYS_CSR_ADDR;
255 		*(volatile int *)MACH_SYS_CSR_ADDR = i & ~(MACH_CSR_MBZ | 0xFF);
256 
257 		/*
258 		 * Probe the TURBOchannel to see what controllers are present.
259 		 */
260 		tc_find_all_options();
261 
262 		/* clear any memory errors from probes */
263 		*(unsigned *)MACH_ERROR_ADDR = 0;
264 
265 		/*
266 		 * Find out how much memory is available.
267 		 */
268 		physmem = btoc(v - KERNBASE);
269 		cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
270 		while (cp < (char *)MACH_MAX_MEM_ADDR) {
271 			if (badaddr(cp, 4))
272 				break;
273 			*(int *)cp = 0xa5a5a5a5;
274 			/*
275 			 * Data will persist on the bus if we read it right
276 			 * away. Have to be tricky here.
277 			 */
278 			((int *)cp)[4] = 0x5a5a5a5a;
279 			MachEmptyWriteBuffer();
280 			if (*(int *)cp != 0xa5a5a5a5)
281 				break;
282 			cp += NBPG;
283 			physmem++;
284 		}
285 		break;
286 	    }
287 #endif DS5000
288 
289 	case 5:	/* DS5800 Isis */
290 	case 6:	/* DS5400 MIPSfair */
291 	default:
292 		printf("kernel not configured for systype 0x%x\n", i);
293 		boot(RB_HALT | RB_NOSYNC);
294 	}
295 
296 	maxmem = physmem;
297 
298 	/*
299 	 * Initialize error message buffer (at end of core).
300 	 */
301 	maxmem -= btoc(sizeof (struct msgbuf));
302 	msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT));
303 	msgbufmapped = 1;
304 
305 	/*
306 	 * Allocate space for system data structures.
307 	 * The first available kernel virtual address is in "v".
308 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
309 	 *
310 	 * These data structures are allocated here instead of cpu_startup()
311 	 * because physical memory is directly addressable. We don't have
312 	 * to map these into virtual address space.
313 	 */
314 	start = v;
315 
316 #define	valloc(name, type, num) \
317 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
318 #define	valloclim(name, type, num, lim) \
319 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
320 	valloc(cfree, struct cblock, nclist);
321 	valloc(callout, struct callout, ncallout);
322 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
323 #ifdef SYSVSHM
324 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
325 #endif
326 #ifdef ATTR
327 	/* this is allocated here just to save a few bytes */
328 	valloc(pmap_attributes, char, physmem);
329 #endif
330 
331 	/*
332 	 * Determine how many buffers to allocate.
333 	 * We allocate more buffer space than the BSD standard of
334 	 * using 10% of memory for the first 2 Meg, 5% of remaining.
335 	 * We just allocate a flat 10%.  Insure a minimum of 16 buffers.
336 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
337 	 */
338 	if (bufpages == 0)
339 		bufpages = physmem / 10 / CLSIZE;
340 	if (nbuf == 0) {
341 		nbuf = bufpages;
342 		if (nbuf < 16)
343 			nbuf = 16;
344 	}
345 	if (nswbuf == 0) {
346 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
347 		if (nswbuf > 256)
348 			nswbuf = 256;		/* sanity */
349 	}
350 	valloc(swbuf, struct buf, nswbuf);
351 	valloc(buf, struct buf, nbuf);
352 
353 	/*
354 	 * Clear allocated memory.
355 	 */
356 	v = (caddr_t)pmax_round_page(v);
357 	bzero(start, v - start);
358 
359 	/*
360 	 * Initialize the virtual memory system.
361 	 */
362 	pmap_bootstrap((vm_offset_t)MACH_CACHED_TO_PHYS(v));
363 }
364 
365 /*
366  * Console initialization: called early on from main,
367  * before vm init or startup.  Do enough configuration
368  * to choose and initialize a console.
369  * XXX need something better here.
370  */
371 consinit()
372 {
373 
374 #include "pm.h"
375 #if NPM > 0
376 	if (pminit())
377 		return;
378 #endif
379 
380 #include "cfb.h"
381 #if NCFB > 0
382 	{
383 		register struct pmax_ctlr *cp;
384 		register struct driver *drp;
385 
386 		for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
387 			if (strcmp(drp->d_name, "cfb"))
388 				continue;
389 			if (cfb_init(cp))
390 				return;
391 		}
392 	}
393 #endif
394 }
395 
396 /*
397  * cpu_startup: allocate memory for variable-sized tables,
398  * initialize cpu, and do autoconfiguration.
399  */
400 cpu_startup()
401 {
402 	register unsigned i;
403 	register caddr_t v;
404 	int base, residual;
405 	extern long Usrptsize;
406 	extern struct map *useriomap;
407 #ifdef DEBUG
408 	extern int pmapdebug;
409 	int opmapdebug = pmapdebug;
410 #endif
411 	vm_offset_t minaddr, maxaddr;
412 	vm_size_t size;
413 
414 #ifdef DEBUG
415 	pmapdebug = 0;
416 #endif
417 
418 	/*
419 	 * Good {morning,afternoon,evening,night}.
420 	 */
421 	printf(version);
422 	printf("real mem = %d\n", ctob(physmem));
423 
424 	/*
425 	 * Allocate virtual address space for file I/O buffers.
426 	 * Note they are different than the array of headers, 'buf',
427 	 * and usually occupy more virtual memory than physical.
428 	 */
429 	size = MAXBSIZE * nbuf;
430 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
431 				   &maxaddr, size, FALSE);
432 	minaddr = (vm_offset_t)buffers;
433 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
434 			&minaddr, size, FALSE) != KERN_SUCCESS)
435 		panic("startup: cannot allocate buffers");
436 	base = bufpages / nbuf;
437 	residual = bufpages % nbuf;
438 	for (i = 0; i < nbuf; i++) {
439 		vm_size_t curbufsize;
440 		vm_offset_t curbuf;
441 
442 		/*
443 		 * First <residual> buffers get (base+1) physical pages
444 		 * allocated for them.  The rest get (base) physical pages.
445 		 *
446 		 * The rest of each buffer occupies virtual space,
447 		 * but has no physical memory allocated for it.
448 		 */
449 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
450 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
451 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
452 		vm_map_simplify(buffer_map, curbuf);
453 	}
454 	/*
455 	 * Allocate a submap for exec arguments.  This map effectively
456 	 * limits the number of processes exec'ing at any time.
457 	 */
458 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
459 				 16*NCARGS, TRUE);
460 	/*
461 	 * Allocate a submap for physio
462 	 */
463 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
464 				 VM_PHYS_SIZE, TRUE);
465 
466 	/*
467 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
468 	 * we use the more space efficient malloc in place of kmem_alloc.
469 	 */
470 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
471 				   M_MBUF, M_NOWAIT);
472 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
473 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
474 			       VM_MBUF_SIZE, FALSE);
475 	/*
476 	 * Initialize callouts
477 	 */
478 	callfree = callout;
479 	for (i = 1; i < ncallout; i++)
480 		callout[i-1].c_next = &callout[i];
481 	callout[i-1].c_next = NULL;
482 
483 #ifdef DEBUG
484 	pmapdebug = opmapdebug;
485 #endif
486 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
487 	printf("using %d buffers containing %d bytes of memory\n",
488 		nbuf, bufpages * CLBYTES);
489 	/*
490 	 * Set up CPU-specific registers, cache, etc.
491 	 */
492 	initcpu();
493 
494 	/*
495 	 * Set up buffers, so they can be used to read disk labels.
496 	 */
497 	bufinit();
498 
499 	/*
500 	 * Configure the system.
501 	 */
502 	configure();
503 }
504 
505 /*
506  * Set registers on exec.
507  * Clear all registers except sp, pc.
508  */
509 setregs(p, entry, retval)
510 	register struct proc *p;
511 	u_long entry;
512 	int retval[2];
513 {
514 	int sp = p->p_md.md_regs[SP];
515 	extern struct proc *machFPCurProcPtr;
516 
517 	bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
518 	p->p_md.md_regs[SP] = sp;
519 	p->p_md.md_regs[PC] = entry & ~3;
520 	p->p_md.md_regs[PS] = PSL_USERSET;
521 	p->p_md.md_flags & ~MDP_FPUSED;
522 	if (machFPCurProcPtr == p)
523 		machFPCurProcPtr = (struct proc *)0;
524 }
525 
526 /*
527  * WARNING: code in locore.s assumes the layout shown for sf_signum
528  * thru sf_handler so... don't screw with them!
529  */
530 struct sigframe {
531 	int	sf_signum;		/* signo for handler */
532 	int	sf_code;		/* additional info for handler */
533 	struct	sigcontext *sf_scp;	/* context ptr for handler */
534 	sig_t	sf_handler;		/* handler addr for u_sigc */
535 	struct	sigcontext sf_sc;	/* actual context */
536 };
537 
538 #ifdef DEBUG
539 int sigdebug = 0;
540 int sigpid = 0;
541 #define SDB_FOLLOW	0x01
542 #define SDB_KSTACK	0x02
543 #define SDB_FPSTATE	0x04
544 #endif
545 
546 /*
547  * Send an interrupt to process.
548  */
549 void
550 sendsig(catcher, sig, mask, code)
551 	sig_t catcher;
552 	int sig, mask;
553 	unsigned code;
554 {
555 	register struct proc *p = curproc;
556 	register struct sigframe *fp;
557 	register int *regs;
558 	register struct sigacts *psp = p->p_sigacts;
559 	int oonstack, fsize;
560 	struct sigcontext ksc;
561 	extern char sigcode[], esigcode[];
562 
563 	regs = p->p_md.md_regs;
564 	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
565 	/*
566 	 * Allocate and validate space for the signal handler
567 	 * context. Note that if the stack is in data space, the
568 	 * call to grow() is a nop, and the copyout()
569 	 * will fail if the process has not already allocated
570 	 * the space with a `brk'.
571 	 */
572 	fsize = sizeof(struct sigframe);
573 	if ((psp->ps_flags & SAS_ALTSTACK) &&
574 	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
575 	    (psp->ps_sigonstack & sigmask(sig))) {
576 		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
577 					 psp->ps_sigstk.ss_size - fsize);
578 		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
579 	} else
580 		fp = (struct sigframe *)(regs[SP] - fsize);
581 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
582 		(void)grow(p, (unsigned)fp);
583 #ifdef DEBUG
584 	if ((sigdebug & SDB_FOLLOW) ||
585 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
586 		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
587 		       p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
588 #endif
589 	/*
590 	 * Build the signal context to be used by sigreturn.
591 	 */
592 	ksc.sc_onstack = oonstack;
593 	ksc.sc_mask = mask;
594 	ksc.sc_pc = regs[PC];
595 	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */
596 	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
597 		sizeof(ksc.sc_regs) - sizeof(int));
598 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
599 	if (ksc.sc_fpused) {
600 		extern struct proc *machFPCurProcPtr;
601 
602 		/* if FPU has current state, save it first */
603 		if (p == machFPCurProcPtr)
604 			MachSaveCurFPState(p);
605 		bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
606 			sizeof(ksc.sc_fpregs));
607 	}
608 	if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
609 		/*
610 		 * Process has trashed its stack; give it an illegal
611 		 * instruction to halt it in its tracks.
612 		 */
613 		SIGACTION(p, SIGILL) = SIG_DFL;
614 		sig = sigmask(SIGILL);
615 		p->p_sigignore &= ~sig;
616 		p->p_sigcatch &= ~sig;
617 		p->p_sigmask &= ~sig;
618 		psignal(p, SIGILL);
619 		return;
620 	}
621 	/*
622 	 * Build the argument list for the signal handler.
623 	 */
624 	regs[A0] = sig;
625 	regs[A1] = code;
626 	regs[A2] = (int)&fp->sf_sc;
627 	regs[A3] = (int)catcher;
628 
629 	regs[PC] = (int)catcher;
630 	regs[SP] = (int)fp;
631 	/*
632 	 * Signal trampoline code is at base of user stack.
633 	 */
634 	regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
635 #ifdef DEBUG
636 	if ((sigdebug & SDB_FOLLOW) ||
637 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
638 		printf("sendsig(%d): sig %d returns\n",
639 		       p->p_pid, sig);
640 #endif
641 }
642 
643 /*
644  * System call to cleanup state after a signal
645  * has been taken.  Reset signal mask and
646  * stack state from context left by sendsig (above).
647  * Return to previous pc and psl as specified by
648  * context left by sendsig. Check carefully to
649  * make sure that the user has not modified the
650  * psl to gain improper priviledges or to cause
651  * a machine fault.
652  */
653 struct sigreturn_args {
654 	struct sigcontext *sigcntxp;
655 };
656 /* ARGSUSED */
657 sigreturn(p, uap, retval)
658 	struct proc *p;
659 	struct sigreturn_args *uap;
660 	int *retval;
661 {
662 	register struct sigcontext *scp;
663 	register int *regs;
664 	struct sigcontext ksc;
665 	int error;
666 
667 	scp = uap->sigcntxp;
668 #ifdef DEBUG
669 	if (sigdebug & SDB_FOLLOW)
670 		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
671 #endif
672 	regs = p->p_md.md_regs;
673 	/*
674 	 * Test and fetch the context structure.
675 	 * We grab it all at once for speed.
676 	 */
677 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
678 	if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
679 #ifdef DEBUG
680 		if (!(sigdebug & SDB_FOLLOW))
681 			printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
682 		printf("  old sp %x ra %x pc %x\n",
683 			regs[SP], regs[RA], regs[PC]);
684 		printf("  new sp %x ra %x pc %x err %d z %x\n",
685 			ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
686 			error, ksc.sc_regs[ZERO]);
687 #endif
688 		return (EINVAL);
689 	}
690 	scp = &ksc;
691 	/*
692 	 * Restore the user supplied information
693 	 */
694 	if (scp->sc_onstack & 01)
695 		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
696 	else
697 		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
698 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
699 	regs[PC] = scp->sc_pc;
700 	bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)&regs[1],
701 		sizeof(scp->sc_regs) - sizeof(int));
702 	if (scp->sc_fpused)
703 		bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
704 			sizeof(scp->sc_fpregs));
705 	return (EJUSTRETURN);
706 }
707 
708 int	waittime = -1;
709 
710 boot(howto)
711 	register int howto;
712 {
713 
714 	/* take a snap shot before clobbering any registers */
715 	if (curproc)
716 		savectx(curproc->p_addr, 0);
717 
718 	howto |= RB_HALT; /* XXX */
719 	boothowto = howto;
720 	if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
721 		register struct buf *bp;
722 		int iter, nbusy;
723 
724 		waittime = 0;
725 		(void) spl0();
726 		printf("syncing disks... ");
727 		/*
728 		 * Release vnodes held by texts before sync.
729 		 */
730 		if (panicstr == 0)
731 			vnode_pager_umount(NULL);
732 #ifdef notdef
733 #include "fd.h"
734 #if NFD > 0
735 		fdshutdown();
736 #endif
737 #endif
738 		sync(&proc0, (void *)NULL, (int *)NULL);
739 
740 		for (iter = 0; iter < 20; iter++) {
741 			nbusy = 0;
742 			for (bp = &buf[nbuf]; --bp >= buf; )
743 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
744 					nbusy++;
745 			if (nbusy == 0)
746 				break;
747 			printf("%d ", nbusy);
748 			DELAY(40000 * iter);
749 		}
750 		if (nbusy)
751 			printf("giving up\n");
752 		else
753 			printf("done\n");
754 		/*
755 		 * If we've been adjusting the clock, the todr
756 		 * will be out of synch; adjust it now.
757 		 */
758 		resettodr();
759 	}
760 	(void) splhigh();		/* extreme priority */
761 	if (howto & RB_HALT) {
762 		void (*f)() = (void (*)())MACH_MON_REINIT;
763 
764 		(*f)();	/* jump back to prom monitor */
765 	} else {
766 		void (*f)() = (void (*)())MACH_MON_AUTOBOOT;
767 
768 		if (howto & RB_DUMP)
769 			dumpsys();
770 		(*f)();	/* jump back to prom monitor and do 'auto' cmd */
771 		/*NOTREACHED*/
772 	}
773 	/*NOTREACHED*/
774 }
775 
776 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
777 int	dumpsize = 0;		/* also for savecore */
778 long	dumplo = 0;
779 
780 dumpconf()
781 {
782 	int nblks;
783 
784 	dumpsize = physmem;
785 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
786 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
787 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
788 			dumpsize = btoc(dbtob(nblks - dumplo));
789 		else if (dumplo == 0)
790 			dumplo = nblks - btodb(ctob(physmem));
791 	}
792 	/*
793 	 * Don't dump on the first CLBYTES (why CLBYTES?)
794 	 * in case the dump device includes a disk label.
795 	 */
796 	if (dumplo < btodb(CLBYTES))
797 		dumplo = btodb(CLBYTES);
798 }
799 
800 /*
801  * Doadump comes here after turning off memory management and
802  * getting on the dump stack, either when called above, or by
803  * the auto-restart code.
804  */
805 dumpsys()
806 {
807 	int error;
808 
809 	msgbufmapped = 0;
810 	if (dumpdev == NODEV)
811 		return;
812 	/*
813 	 * For dumps during autoconfiguration,
814 	 * if dump device has already configured...
815 	 */
816 	if (dumpsize == 0)
817 		dumpconf();
818 	if (dumplo < 0)
819 		return;
820 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
821 	printf("dump ");
822 	switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
823 
824 	case ENXIO:
825 		printf("device bad\n");
826 		break;
827 
828 	case EFAULT:
829 		printf("device not ready\n");
830 		break;
831 
832 	case EINVAL:
833 		printf("area improper\n");
834 		break;
835 
836 	case EIO:
837 		printf("i/o error\n");
838 		break;
839 
840 	default:
841 		printf("error %d\n", error);
842 		break;
843 
844 	case 0:
845 		printf("succeeded\n");
846 	}
847 }
848 
849 /*
850  * Return the best possible estimate of the time in the timeval
851  * to which tvp points.  Unfortunately, we can't read the hardware registers.
852  * We guarantee that the time will be greater than the value obtained by a
853  * previous call.
854  */
855 microtime(tvp)
856 	register struct timeval *tvp;
857 {
858 	int s = splclock();
859 	static struct timeval lasttime;
860 
861 	*tvp = time;
862 #ifdef notdef
863 	tvp->tv_usec += clkread();
864 	while (tvp->tv_usec > 1000000) {
865 		tvp->tv_sec++;
866 		tvp->tv_usec -= 1000000;
867 	}
868 #endif
869 	if (tvp->tv_sec == lasttime.tv_sec &&
870 	    tvp->tv_usec <= lasttime.tv_usec &&
871 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
872 		tvp->tv_sec++;
873 		tvp->tv_usec -= 1000000;
874 	}
875 	lasttime = *tvp;
876 	splx(s);
877 }
878 
879 initcpu()
880 {
881 	register volatile struct chiptime *c;
882 	int i;
883 
884 	/* disable clock interrupts (until startrtclock()) */
885 	c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
886 	c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
887 	i = c->regc;
888 	spl0();		/* safe to turn interrupts on now */
889 	return (i);
890 }
891 
892 /*
893  * Convert an ASCII string into an integer.
894  */
895 int
896 atoi(s)
897 	char *s;
898 {
899 	int c;
900 	unsigned base = 10, d;
901 	int neg = 0, val = 0;
902 
903 	if (s == 0 || (c = *s++) == 0)
904 		goto out;
905 
906 	/* skip spaces if any */
907 	while (c == ' ' || c == '\t')
908 		c = *s++;
909 
910 	/* parse sign, allow more than one (compat) */
911 	while (c == '-') {
912 		neg = !neg;
913 		c = *s++;
914 	}
915 
916 	/* parse base specification, if any */
917 	if (c == '0') {
918 		c = *s++;
919 		switch (c) {
920 		case 'X':
921 		case 'x':
922 			base = 16;
923 			break;
924 		case 'B':
925 		case 'b':
926 			base = 2;
927 			break;
928 		default:
929 			base = 8;
930 			break;
931 		}
932 	}
933 
934 	/* parse number proper */
935 	for (;;) {
936 		if (c >= '0' && c <= '9')
937 			d = c - '0';
938 		else if (c >= 'a' && c <= 'z')
939 			d = c - 'a' + 10;
940 		else if (c >= 'A' && c <= 'Z')
941 			d = c - 'A' + 10;
942 		else
943 			break;
944 		val *= base;
945 		val += d;
946 		c = *s++;
947 	}
948 	if (neg)
949 		val = -val;
950 out:
951 	return val;
952 }
953 
954 #ifdef DS5000
955 /*
956  * Mach Operating System
957  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
958  * All Rights Reserved.
959  *
960  * Permission to use, copy, modify and distribute this software and its
961  * documentation is hereby granted, provided that both the copyright
962  * notice and this permission notice appear in all copies of the
963  * software, derivative works or modified versions, and any portions
964  * thereof, and that both notices appear in supporting documentation.
965  *
966  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
967  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
968  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
969  *
970  * Carnegie Mellon requests users of this software to return to
971  *
972  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
973  *  School of Computer Science
974  *  Carnegie Mellon University
975  *  Pittsburgh PA 15213-3890
976  *
977  * any improvements or extensions that they make and grant Carnegie the
978  * rights to redistribute these changes.
979  */
980 
981 #include <pmax/pmax/turbochannel.h>
982 
983 /*
984  * Driver map: associates a device driver to an option type.
985  * Drivers name are (arbitrarily) defined in each driver and
986  * used in the various config tables.
987  */
988 struct drivers_map {
989 	char	module_name[TC_ROM_LLEN];	/* from ROM, literally! */
990 	char	*driver_name;			/* in bus_??_init[] tables */
991 } tc_drivers_map[] = {
992 	{ "KN02    ",	"dc"},		/* system board, serial I/O */
993 	{ "PMAD-AA ",	"le"},		/* Ether */
994 	{ "PMAZ-AA ",	"asc"},		/* SCSI */
995 	{ "PMAG-BA ",	"cfb"},		/* Color Frame Buffer */
996 	{ "PMAG-CA ",	"ga"},		/* 2D graphic board */
997 	{ "PMAG-DA ",	"gq"},		/* 3D graphic board (LM) */
998 	{ "PMAG-FA ",	"gq"},		/* 3D graphic board (HE) */
999 
1000 	{ "", 0}			/* list end */
1001 };
1002 
1003 #ifdef DEBUG
1004 int tc_verbose = 0;
1005 #endif
1006 
1007 /*
1008  * TURBOchannel autoconf procedure. Finds in one sweep what is
1009  * hanging on the bus and fills in the tc_slot_info array.
1010  * This is only the first part of the autoconf scheme, at this
1011  * time we are basically only looking for a graphics board and
1012  * serial port to use as system console (all workstations).
1013  *
1014  * XXX Someday make number of slots dynamic too.
1015  */
1016 
1017 #define KN02_TC_NSLOTS	8
1018 
1019 tc_option_t	tc_slot_info[KN02_TC_NSLOTS];
1020 
1021 caddr_t	tc_slot_virt_addr[] = {
1022 	(caddr_t)0xbe000000,	/* TURBOchannel, slot 0 */
1023 	(caddr_t)0xbe400000,	/* TURBOchannel, slot 1 */
1024 	(caddr_t)0xbe800000,	/* TURBOchannel, slot 2 */
1025 	(caddr_t)0xbec00000,	/* TURBOchannel, slot 3 */
1026 	(caddr_t)0xbf000000,	/* TURBOchannel, slot 4 */
1027 	(caddr_t)0xbf400000,	/* TURBOchannel, slot 5 */
1028 	(caddr_t)0xbf800000,	/* TURBOchannel, slot 6 */
1029 /*	(caddr_t)0xbfc00000,	   TURBOchannel, slot 7 */
1030 };
1031 
1032 void
1033 tc_find_all_options()
1034 {
1035 	register int i;
1036 	caddr_t addr;
1037 	register tc_option_t *sl;
1038 	register struct drivers_map *map;
1039 	register struct pmax_ctlr *cp;
1040 	register struct driver *drp;
1041 
1042 	/*
1043 	 * Look for all controllers on the bus.
1044 	 */
1045 	i = sizeof(tc_slot_virt_addr) / sizeof(tc_slot_virt_addr[0]) - 1;
1046 	while (i >= 0) {
1047 		addr = tc_slot_virt_addr[i];
1048 		if (tc_probe_slot(addr, &tc_slot_info[i])) {
1049 			/*
1050 			 * Found a slot, make a note of it
1051 			 */
1052 			tc_slot_info[i].present = 1;
1053 			tc_slot_info[i].module_address = addr;
1054 		}
1055 
1056 		i -= tc_slot_info[i].slot_size;
1057 	}
1058 
1059 	/*
1060 	 * Now for each slot found, see if we have a device driver that
1061 	 * handles it.
1062 	 */
1063 	for (i = 0, sl = tc_slot_info; i < KN02_TC_NSLOTS; i++, sl++) {
1064 		if (!sl->present)
1065 			continue;
1066 		/*
1067 		 * Look for mapping between the module name and
1068 		 * the device driver name.
1069 		 */
1070 		for (map = tc_drivers_map; map->driver_name; map++) {
1071 			if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
1072 				continue;
1073 			goto fnd_map;
1074 		}
1075 #ifdef DEBUG
1076 		if (tc_verbose)
1077 			printf("Cannot associate a device driver to %s\n",
1078 				sl->module_name);
1079 #endif
1080 		sl->present = 0;
1081 		continue;
1082 
1083 		/*
1084 		 * Find the device driver entry and fill in the address.
1085 		 */
1086 	fnd_map:
1087 		for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1088 			if (strcmp(drp->d_name, map->driver_name))
1089 				continue;
1090 			if (cp->pmax_addr == (char *)QUES) {
1091 				cp->pmax_addr = sl->module_address;
1092 				cp->pmax_pri = i;
1093 				continue;
1094 			}
1095 			if (cp->pmax_addr != sl->module_address) {
1096 				cp->pmax_addr = (char *)QUES;
1097 				printf("%s: device not at configued address (expected at %x, found at %x)\n",
1098 					drp->d_name,
1099 					cp->pmax_addr, sl->module_address);
1100 			}
1101 		}
1102 	}
1103 }
1104 
1105 /*
1106  * Probe a slot in the TURBOchannel. Return TRUE if a valid option
1107  * is present, FALSE otherwise. A side-effect is to fill the slot
1108  * descriptor with the size of the option, whether it is
1109  * recognized or not.
1110  */
1111 int
1112 tc_probe_slot(addr, slot)
1113 	caddr_t addr;
1114 	tc_option_t *slot;
1115 {
1116 	int i;
1117 	static unsigned tc_offset_rom[] = {
1118 		TC_OFF_PROTO_ROM, TC_OFF_ROM
1119 	};
1120 #define TC_N_OFFSETS	sizeof(tc_offset_rom)/sizeof(unsigned)
1121 
1122 	slot->slot_size = 1;
1123 
1124 	for (i = 0; i < TC_N_OFFSETS; i++) {
1125 		if (badaddr(addr + tc_offset_rom[i], 4))
1126 			continue;
1127 		/* complain only on last chance */
1128 		if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]),
1129 		    slot, i == (TC_N_OFFSETS-1)))
1130 			return (1);
1131 	}
1132 	return (0);
1133 #undef TC_N_OFFSETS
1134 }
1135 
1136 /*
1137  * Identify an option on the TURBOchannel.  Looks at the mandatory
1138  * info in the option's ROM and checks it.
1139  */
1140 int
1141 tc_identify_option(addr, slot, complain)
1142 	tc_rommap_t *addr;
1143 	tc_option_t *slot;
1144 	int complain;
1145 {
1146 	register int i;
1147 	unsigned char width;
1148 	char firmwr[TC_ROM_LLEN+1];
1149 	char vendor[TC_ROM_LLEN+1];
1150 	char module[TC_ROM_LLEN+1];
1151 	char host_type[TC_ROM_SLEN+1];
1152 
1153 	/*
1154 	 * We do not really use the 'width' info, but take advantage
1155 	 * of the restriction that the spec impose on the portion
1156 	 * of the ROM that maps between +0x3e0 and +0x470, which
1157 	 * is the only piece we need to look at.
1158 	 */
1159 	width = addr->rom_width.value;
1160 	switch (width) {
1161 	case 1:
1162 	case 2:
1163 	case 4:
1164 		break;
1165 
1166 	default:
1167 		if (complain)
1168 			printf("Invalid ROM width (0x%x) at x%x\n",
1169 			       width, addr);
1170 		return (0);
1171 	}
1172 
1173 	if (addr->rom_stride.value != 4) {
1174 		if (complain)
1175 			printf("Invalid ROM stride (0x%x) at x%x\n",
1176 			       addr->rom_stride.value, addr);
1177 		return (0);
1178 	}
1179 
1180 	if (addr->test_data[0] != 0x55 ||
1181 	    addr->test_data[4] != 0x00 ||
1182 	    addr->test_data[8] != 0xaa ||
1183 	    addr->test_data[12] != 0xff) {
1184 		if (complain)
1185 			printf("Test pattern failed, option at x%x\n",
1186 			       addr);
1187 		return (0);
1188 	}
1189 
1190 	for (i = 0; i < TC_ROM_LLEN; i++) {
1191 		firmwr[i] = addr->firmware_rev[i].value;
1192 		vendor[i] = addr->vendor_name[i].value;
1193 		module[i] = addr->module_name[i].value;
1194 		if (i >= TC_ROM_SLEN)
1195 			continue;
1196 		host_type[i] = addr->host_firmware_type[i].value;
1197 	}
1198 
1199 #ifdef DEBUG
1200 	if (tc_verbose) {
1201 		firmwr[TC_ROM_LLEN] = '\0';
1202 		vendor[TC_ROM_LLEN] = '\0';
1203 		module[TC_ROM_LLEN] = '\0';
1204 		host_type[TC_ROM_SLEN] = '\0';
1205 		printf("%s %s '%s' at x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
1206 		       "Found a", vendor, module, addr,
1207 		       "Firmware rev.", firmwr,
1208 		       "diagnostics for a", host_type,
1209 		       "ROM size is", addr->rom_size.value << 3,
1210 		       "Kbytes, uses", addr->slot_size.value, "TC slot(s)");
1211 	}
1212 #endif
1213 
1214 	bcopy(module, slot->module_name, TC_ROM_LLEN);
1215 	bcopy(vendor, slot->module_id, TC_ROM_LLEN);
1216 	bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
1217 	slot->slot_size = addr->slot_size.value;
1218 	slot->rom_width = width;
1219 
1220 	return (1);
1221 }
1222 
1223 /*
1224  * Enable/Disable interrupts for a TURBOchannel slot.
1225  */
1226 tc_enable_interrupt(slotno, on)
1227 	register int slotno;
1228 	int on;
1229 {
1230 	register volatile int *p_csr = (volatile int *)MACH_SYS_CSR_ADDR;
1231 	int csr;
1232 	int s;
1233 
1234 	slotno = 1 << (slotno + MACH_CSR_IOINTEN_SHIFT);
1235 	s = Mach_spl0();
1236 	csr = *p_csr & ~(MACH_CSR_MBZ | 0xFF);
1237 	if (on)
1238 		*p_csr = csr | slotno;
1239 	else
1240 		*p_csr = csr & ~slotno;
1241 	splx(s);
1242 }
1243 
1244 #endif /* DS5000 */
1245