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