xref: /original-bsd/sys/pmax/pmax/machdep.c (revision 753853ba)
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.5 (Berkeley) 03/22/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 
481 #ifdef DEBUG
482 	pmapdebug = opmapdebug;
483 #endif
484 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
485 	printf("using %d buffers containing %d bytes of memory\n",
486 		nbuf, bufpages * CLBYTES);
487 	/*
488 	 * Set up CPU-specific registers, cache, etc.
489 	 */
490 	initcpu();
491 
492 	/*
493 	 * Set up buffers, so they can be used to read disk labels.
494 	 */
495 	bufinit();
496 
497 	/*
498 	 * Configure the system.
499 	 */
500 	configure();
501 }
502 
503 /*
504  * Set registers on exec.
505  * Clear all registers except sp, pc.
506  */
507 setregs(p, entry, retval)
508 	register struct proc *p;
509 	u_long entry;
510 	int retval[2];
511 {
512 	int sp = p->p_md.md_regs[SP];
513 	extern struct proc *machFPCurProcPtr;
514 
515 	bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
516 	p->p_md.md_regs[SP] = sp;
517 	p->p_md.md_regs[PC] = entry;
518 	p->p_md.md_regs[PS] = PSL_USERSET;
519 	p->p_md.md_flags & ~MDP_FPUSED;
520 	if (machFPCurProcPtr == p)
521 		machFPCurProcPtr = (struct proc *)0;
522 }
523 
524 /*
525  * WARNING: code in locore.s assumes the layout shown for sf_signum
526  * thru sf_handler so... don't screw with them!
527  */
528 struct sigframe {
529 	int	sf_signum;		/* signo for handler */
530 	int	sf_code;		/* additional info for handler */
531 	struct	sigcontext *sf_scp;	/* context ptr for handler */
532 	sig_t	sf_handler;		/* handler addr for u_sigc */
533 };
534 
535 #ifdef DEBUG
536 int sigdebug = 0;
537 int sigpid = 0;
538 #define SDB_FOLLOW	0x01
539 #define SDB_KSTACK	0x02
540 #define SDB_FPSTATE	0x04
541 #endif
542 
543 /*
544  * Send an interrupt to process.
545  */
546 void
547 sendsig(catcher, sig, mask, code)
548 	sig_t catcher;
549 	int sig, mask;
550 	unsigned code;
551 {
552 	register struct proc *p = curproc;
553 	register struct sigframe *fp;
554 	register struct sigacts *ps = p->p_sigacts;
555 	register struct sigcontext *scp;
556 	register int *regs;
557 	int oonstack, fsize;
558 	struct sigcontext ksc;
559 
560 	regs = p->p_md.md_regs;
561 	oonstack = ps->ps_onstack;
562 	/*
563 	 * Allocate and validate space for the signal handler
564 	 * context. Note that if the stack is in data space, the
565 	 * call to grow() is a nop, and the copyout()
566 	 * will fail if the process has not already allocated
567 	 * the space with a `brk'.
568 	 */
569 	if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
570 		scp = (struct sigcontext *)ps->ps_sigsp - 1;
571 		ps->ps_onstack = 1;
572 	} else
573 		scp = (struct sigcontext *)regs[SP] - 1;
574 	fp = (struct sigframe *)scp - 1;
575 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
576 		(void)grow(p, (unsigned)fp);
577 	/*
578 	 * Build the signal context to be used by sigreturn.
579 	 */
580 	ksc.sc_onstack = oonstack;
581 	ksc.sc_mask = mask;
582 	ksc.sc_pc = regs[PC];
583 	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */
584 	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
585 		sizeof(ksc.sc_regs) - sizeof(int));
586 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
587 	if (ksc.sc_fpused) {
588 		extern struct proc *machFPCurProcPtr;
589 
590 		/* if FPU has current state, save it first */
591 		if (p == machFPCurProcPtr)
592 			MachSaveCurFPState(p);
593 		bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
594 			sizeof(ksc.sc_fpregs));
595 	}
596 	if (copyout((caddr_t)&ksc, (caddr_t)scp, sizeof(ksc))) {
597 		/*
598 		 * Process has trashed its stack; give it an illegal
599 		 * instruction to halt it in its tracks.
600 		 */
601 		SIGACTION(p, SIGILL) = SIG_DFL;
602 		sig = sigmask(SIGILL);
603 		p->p_sigignore &= ~sig;
604 		p->p_sigcatch &= ~sig;
605 		p->p_sigmask &= ~sig;
606 		psignal(p, SIGILL);
607 		return;
608 	}
609 	/*
610 	 * Build the argument list for the signal handler.
611 	 */
612 	regs[A0] = sig;
613 	regs[A1] = code;
614 	regs[A2] = (int)scp;
615 	regs[A3] = (int)catcher;
616 
617 	regs[PC] = (int)catcher;
618 	regs[SP] = (int)fp;
619 	regs[RA] = KERNBASE;	/* this causes a trap which we interpret as
620 				 * meaning "do a sigreturn". */
621 #ifdef DEBUG
622 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
623 		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
624 		       p->p_pid, sig, &oonstack, fp, fp->sf_scp);
625 #endif
626 }
627 
628 /*
629  * System call to cleanup state after a signal
630  * has been taken.  Reset signal mask and
631  * stack state from context left by sendsig (above).
632  * Return to previous pc and psl as specified by
633  * context left by sendsig. Check carefully to
634  * make sure that the user has not modified the
635  * psl to gain improper priviledges or to cause
636  * a machine fault.
637  */
638 /* ARGSUSED */
639 sigreturn(p, uap, retval)
640 	struct proc *p;
641 	struct args {
642 		struct sigcontext *sigcntxp;
643 	} *uap;
644 	int *retval;
645 {
646 	register struct sigcontext *scp;
647 	register int *regs;
648 	struct sigcontext ksc;
649 	int error;
650 
651 	register struct frame *frame;
652 	register int rf;
653 	struct sigcontext tsigc;
654 	int flags;
655 
656 	scp = uap->sigcntxp;
657 #ifdef DEBUG
658 	if (sigdebug & SDB_FOLLOW)
659 		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
660 #endif
661 	regs = p->p_md.md_regs;
662 	/*
663 	 * Test and fetch the context structure.
664 	 * We grab it all at once for speed.
665 	 */
666 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
667 	if (error != 0 || ksc.sc_regs[ZERO] != 0xACEDBADE ||
668 	    (unsigned)ksc.sc_regs[SP] < (unsigned)regs[SP]) {
669 #ifdef DEBUG
670 		if (!(sigdebug & SDB_FOLLOW))
671 			printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
672 		printf("  old sp %x ra %x pc %x\n",
673 			regs[SP], regs[RA], regs[PC]);
674 		printf("  new sp %x ra %x pc %x err %d z %x\n",
675 			ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
676 			error, ksc.sc_regs[ZERO]);
677 #endif
678 		if (regs[PC] == KERNBASE) {
679 			int sig;
680 
681 			/*
682 			 * Process has trashed its stack; give it an illegal
683 			 * instruction to halt it in its tracks.
684 			 */
685 			SIGACTION(p, SIGILL) = SIG_DFL;
686 			sig = sigmask(SIGILL);
687 			p->p_sigignore &= ~sig;
688 			p->p_sigcatch &= ~sig;
689 			p->p_sigmask &= ~sig;
690 			psignal(p, SIGILL);
691 		}
692 		return (EINVAL);
693 	}
694 	/*
695 	 * Restore the user supplied information
696 	 */
697 	p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
698 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
699 	regs[PC] = ksc.sc_pc;
700 	bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)&regs[1],
701 		sizeof(ksc.sc_regs) - sizeof(int));
702 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
703 	if (ksc.sc_fpused)
704 		bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
705 			sizeof(ksc.sc_fpregs));
706 	return (EJUSTRETURN);
707 }
708 
709 int	waittime = -1;
710 
711 boot(howto)
712 	register int howto;
713 {
714 
715 	/* take a snap shot before clobbering any registers */
716 	if (curproc)
717 		savectx(curproc->p_addr, 0);
718 
719 	howto |= RB_HALT; /* XXX */
720 	boothowto = howto;
721 	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
722 		register struct buf *bp;
723 		int iter, nbusy;
724 
725 		waittime = 0;
726 		(void) spl0();
727 		printf("syncing disks... ");
728 		/*
729 		 * Release vnodes held by texts before sync.
730 		 */
731 		if (panicstr == 0)
732 			vnode_pager_umount(NULL);
733 #ifdef notdef
734 #include "fd.h"
735 #if NFD > 0
736 		fdshutdown();
737 #endif
738 #endif
739 		sync(&proc0, (void *)NULL, (int *)NULL);
740 
741 		for (iter = 0; iter < 20; iter++) {
742 			nbusy = 0;
743 			for (bp = &buf[nbuf]; --bp >= buf; )
744 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
745 					nbusy++;
746 			if (nbusy == 0)
747 				break;
748 			printf("%d ", nbusy);
749 			DELAY(40000 * iter);
750 		}
751 		if (nbusy)
752 			printf("giving up\n");
753 		else
754 			printf("done\n");
755 		/*
756 		 * If we've been adjusting the clock, the todr
757 		 * will be out of synch; adjust it now.
758 		 */
759 		resettodr();
760 	}
761 	(void) splhigh();		/* extreme priority */
762 	if (howto & RB_HALT) {
763 		void (*f)() = (void (*)())MACH_MON_REINIT;
764 
765 		(*f)();	/* jump back to prom monitor */
766 	} else {
767 		void (*f)() = (void (*)())MACH_MON_AUTOBOOT;
768 
769 		if (howto & RB_DUMP)
770 			dumpsys();
771 		(*f)();	/* jump back to prom monitor and do 'auto' cmd */
772 		/*NOTREACHED*/
773 	}
774 	/*NOTREACHED*/
775 }
776 
777 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
778 int	dumpsize = 0;		/* also for savecore */
779 long	dumplo = 0;
780 
781 dumpconf()
782 {
783 	int nblks;
784 
785 	dumpsize = physmem;
786 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
787 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
788 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
789 			dumpsize = btoc(dbtob(nblks - dumplo));
790 		else if (dumplo == 0)
791 			dumplo = nblks - btodb(ctob(physmem));
792 	}
793 	/*
794 	 * Don't dump on the first CLBYTES (why CLBYTES?)
795 	 * in case the dump device includes a disk label.
796 	 */
797 	if (dumplo < btodb(CLBYTES))
798 		dumplo = btodb(CLBYTES);
799 }
800 
801 /*
802  * Doadump comes here after turning off memory management and
803  * getting on the dump stack, either when called above, or by
804  * the auto-restart code.
805  */
806 dumpsys()
807 {
808 	int error;
809 
810 	msgbufmapped = 0;
811 	if (dumpdev == NODEV)
812 		return;
813 	/*
814 	 * For dumps during autoconfiguration,
815 	 * if dump device has already configured...
816 	 */
817 	if (dumpsize == 0)
818 		dumpconf();
819 	if (dumplo < 0)
820 		return;
821 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
822 	printf("dump ");
823 	switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
824 
825 	case ENXIO:
826 		printf("device bad\n");
827 		break;
828 
829 	case EFAULT:
830 		printf("device not ready\n");
831 		break;
832 
833 	case EINVAL:
834 		printf("area improper\n");
835 		break;
836 
837 	case EIO:
838 		printf("i/o error\n");
839 		break;
840 
841 	default:
842 		printf("error %d\n", error);
843 		break;
844 
845 	case 0:
846 		printf("succeeded\n");
847 	}
848 }
849 
850 /*
851  * Return the best possible estimate of the time in the timeval
852  * to which tvp points.  Unfortunately, we can't read the hardware registers.
853  * We guarantee that the time will be greater than the value obtained by a
854  * previous call.
855  */
856 microtime(tvp)
857 	register struct timeval *tvp;
858 {
859 	int s = splclock();
860 	static struct timeval lasttime;
861 
862 	*tvp = time;
863 #ifdef notdef
864 	tvp->tv_usec += clkread();
865 	while (tvp->tv_usec > 1000000) {
866 		tvp->tv_sec++;
867 		tvp->tv_usec -= 1000000;
868 	}
869 #endif
870 	if (tvp->tv_sec == lasttime.tv_sec &&
871 	    tvp->tv_usec <= lasttime.tv_usec &&
872 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
873 		tvp->tv_sec++;
874 		tvp->tv_usec -= 1000000;
875 	}
876 	lasttime = *tvp;
877 	splx(s);
878 }
879 
880 initcpu()
881 {
882 	register volatile struct chiptime *c;
883 	int i;
884 
885 	/* disable clock interrupts (until startrtclock()) */
886 	c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
887 	c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
888 	i = c->regc;
889 	spl0();		/* safe to turn interrupts on now */
890 	return (i);
891 }
892 
893 /*
894  * Convert an ASCII string into an integer.
895  */
896 int
897 atoi(s)
898 	char *s;
899 {
900 	int c;
901 	unsigned base = 10, d;
902 	int neg = 0, val = 0;
903 
904 	if (s == 0 || (c = *s++) == 0)
905 		goto out;
906 
907 	/* skip spaces if any */
908 	while (c == ' ' || c == '\t')
909 		c = *s++;
910 
911 	/* parse sign, allow more than one (compat) */
912 	while (c == '-') {
913 		neg = !neg;
914 		c = *s++;
915 	}
916 
917 	/* parse base specification, if any */
918 	if (c == '0') {
919 		c = *s++;
920 		switch (c) {
921 		case 'X':
922 		case 'x':
923 			base = 16;
924 			break;
925 		case 'B':
926 		case 'b':
927 			base = 2;
928 			break;
929 		default:
930 			base = 8;
931 			break;
932 		}
933 	}
934 
935 	/* parse number proper */
936 	for (;;) {
937 		if (c >= '0' && c <= '9')
938 			d = c - '0';
939 		else if (c >= 'a' && c <= 'z')
940 			d = c - 'a' + 10;
941 		else if (c >= 'A' && c <= 'Z')
942 			d = c - 'A' + 10;
943 		else
944 			break;
945 		val *= base;
946 		val += d;
947 		c = *s++;
948 	}
949 	if (neg)
950 		val = -val;
951 out:
952 	return val;
953 }
954 
955 #ifdef DS5000
956 /*
957  * Mach Operating System
958  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
959  * All Rights Reserved.
960  *
961  * Permission to use, copy, modify and distribute this software and its
962  * documentation is hereby granted, provided that both the copyright
963  * notice and this permission notice appear in all copies of the
964  * software, derivative works or modified versions, and any portions
965  * thereof, and that both notices appear in supporting documentation.
966  *
967  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
968  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
969  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
970  *
971  * Carnegie Mellon requests users of this software to return to
972  *
973  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
974  *  School of Computer Science
975  *  Carnegie Mellon University
976  *  Pittsburgh PA 15213-3890
977  *
978  * any improvements or extensions that they make and grant Carnegie the
979  * rights to redistribute these changes.
980  */
981 
982 #include "turbochannel.h"
983 
984 /*
985  * Driver map: associates a device driver to an option type.
986  * Drivers name are (arbitrarily) defined in each driver and
987  * used in the various config tables.
988  */
989 struct drivers_map {
990 	char	module_name[TC_ROM_LLEN];	/* from ROM, literally! */
991 	char	*driver_name;			/* in bus_??_init[] tables */
992 } tc_drivers_map[] = {
993 	{ "KN02    ",	"dc"},		/* system board, serial I/O */
994 	{ "PMAD-AA ",	"le"},		/* Ether */
995 	{ "PMAZ-AA ",	"asc"},		/* SCSI */
996 	{ "PMAG-BA ",	"cfb"},		/* Color Frame Buffer */
997 	{ "PMAG-CA ",	"ga"},		/* 2D graphic board */
998 	{ "PMAG-DA ",	"gq"},		/* 3D graphic board (LM) */
999 	{ "PMAG-FA ",	"gq"},		/* 3D graphic board (HE) */
1000 
1001 	{ "", 0}			/* list end */
1002 };
1003 
1004 #ifdef DEBUG
1005 int tc_verbose = 0;
1006 #endif
1007 
1008 /*
1009  * TURBOchannel autoconf procedure. Finds in one sweep what is
1010  * hanging on the bus and fills in the tc_slot_info array.
1011  * This is only the first part of the autoconf scheme, at this
1012  * time we are basically only looking for a graphics board and
1013  * serial port to use as system console (all workstations).
1014  *
1015  * XXX Someday make number of slots dynamic too.
1016  */
1017 
1018 #define KN02_TC_NSLOTS	8
1019 
1020 tc_option_t	tc_slot_info[KN02_TC_NSLOTS];
1021 
1022 caddr_t	tc_slot_virt_addr[] = {
1023 	(caddr_t)0xbe000000,	/* TURBOchannel, slot 0 */
1024 	(caddr_t)0xbe400000,	/* TURBOchannel, slot 1 */
1025 	(caddr_t)0xbe800000,	/* TURBOchannel, slot 2 */
1026 	(caddr_t)0xbec00000,	/* TURBOchannel, slot 3 */
1027 	(caddr_t)0xbf000000,	/* TURBOchannel, slot 4 */
1028 	(caddr_t)0xbf400000,	/* TURBOchannel, slot 5 */
1029 	(caddr_t)0xbf800000,	/* TURBOchannel, slot 6 */
1030 /*	(caddr_t)0xbfc00000,	   TURBOchannel, slot 7 */
1031 };
1032 
1033 void
1034 tc_find_all_options()
1035 {
1036 	register int i;
1037 	caddr_t addr;
1038 	register tc_option_t *sl;
1039 	register struct drivers_map *map;
1040 	register struct pmax_ctlr *cp;
1041 	register struct driver *drp;
1042 
1043 	/*
1044 	 * Look for all controllers on the bus.
1045 	 */
1046 	i = sizeof(tc_slot_virt_addr) / sizeof(tc_slot_virt_addr[0]) - 1;
1047 	while (i >= 0) {
1048 		addr = tc_slot_virt_addr[i];
1049 		if (tc_probe_slot(addr, &tc_slot_info[i])) {
1050 			/*
1051 			 * Found a slot, make a note of it
1052 			 */
1053 			tc_slot_info[i].present = 1;
1054 			tc_slot_info[i].module_address = addr;
1055 		}
1056 
1057 		i -= tc_slot_info[i].slot_size;
1058 	}
1059 
1060 	/*
1061 	 * Now for each slot found, see if we have a device driver that
1062 	 * handles it.
1063 	 */
1064 	for (i = 0, sl = tc_slot_info; i < KN02_TC_NSLOTS; i++, sl++) {
1065 		if (!sl->present)
1066 			continue;
1067 		/*
1068 		 * Look for mapping between the module name and
1069 		 * the device driver name.
1070 		 */
1071 		for (map = tc_drivers_map; map->driver_name; map++) {
1072 			if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
1073 				continue;
1074 			goto fnd_map;
1075 		}
1076 		if (tc_verbose)
1077 			printf("Cannot associate a device driver to %s\n",
1078 				sl->module_name);
1079 		sl->present = 0;
1080 		continue;
1081 
1082 		/*
1083 		 * Find the device driver entry and fill in the address.
1084 		 */
1085 	fnd_map:
1086 		for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1087 			if (strcmp(drp->d_name, map->driver_name))
1088 				continue;
1089 			if (cp->pmax_addr == (char *)QUES) {
1090 				cp->pmax_addr = sl->module_address;
1091 				cp->pmax_pri = i;
1092 				continue;
1093 			}
1094 			if (cp->pmax_addr != sl->module_address) {
1095 				cp->pmax_addr = (char *)QUES;
1096 				printf("%s: device not at configued address (expected at %x, found at %x)\n",
1097 					drp->d_name,
1098 					cp->pmax_addr, sl->module_address);
1099 			}
1100 		}
1101 	}
1102 }
1103 
1104 /*
1105  * Probe a slot in the TURBOchannel. Return TRUE if a valid option
1106  * is present, FALSE otherwise. A side-effect is to fill the slot
1107  * descriptor with the size of the option, whether it is
1108  * recognized or not.
1109  */
1110 int
1111 tc_probe_slot(addr, slot)
1112 	caddr_t addr;
1113 	tc_option_t *slot;
1114 {
1115 	int i;
1116 	static unsigned tc_offset_rom[] = {
1117 		TC_OFF_PROTO_ROM, TC_OFF_ROM
1118 	};
1119 #define TC_N_OFFSETS	sizeof(tc_offset_rom)/sizeof(unsigned)
1120 
1121 	slot->slot_size = 1;
1122 
1123 	for (i = 0; i < TC_N_OFFSETS; i++) {
1124 		if (badaddr(addr + tc_offset_rom[i], 4))
1125 			continue;
1126 		/* complain only on last chance */
1127 		if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]),
1128 		    slot, i == (TC_N_OFFSETS-1)))
1129 			return (1);
1130 	}
1131 	return (0);
1132 #undef TC_N_OFFSETS
1133 }
1134 
1135 /*
1136  * Identify an option on the TURBOchannel.  Looks at the mandatory
1137  * info in the option's ROM and checks it.
1138  */
1139 int
1140 tc_identify_option(addr, slot, complain)
1141 	tc_rommap_t *addr;
1142 	tc_option_t *slot;
1143 	int complain;
1144 {
1145 	register int i;
1146 	unsigned char width;
1147 	char firmwr[TC_ROM_LLEN+1];
1148 	char vendor[TC_ROM_LLEN+1];
1149 	char module[TC_ROM_LLEN+1];
1150 	char host_type[TC_ROM_SLEN+1];
1151 
1152 	/*
1153 	 * We do not really use the 'width' info, but take advantage
1154 	 * of the restriction that the spec impose on the portion
1155 	 * of the ROM that maps between +0x3e0 and +0x470, which
1156 	 * is the only piece we need to look at.
1157 	 */
1158 	width = addr->rom_width.value;
1159 	switch (width) {
1160 	case 1:
1161 	case 2:
1162 	case 4:
1163 		break;
1164 
1165 	default:
1166 		if (complain)
1167 			printf("Invalid ROM width (0x%x) at x%x\n",
1168 			       width, addr);
1169 		return (0);
1170 	}
1171 
1172 	if (addr->rom_stride.value != 4) {
1173 		if (complain)
1174 			printf("Invalid ROM stride (0x%x) at x%x\n",
1175 			       addr->rom_stride.value, addr);
1176 		return (0);
1177 	}
1178 
1179 	if (addr->test_data[0] != 0x55 ||
1180 	    addr->test_data[4] != 0x00 ||
1181 	    addr->test_data[8] != 0xaa ||
1182 	    addr->test_data[12] != 0xff) {
1183 		if (complain)
1184 			printf("Test pattern failed, option at x%x\n",
1185 			       addr);
1186 		return (0);
1187 	}
1188 
1189 	for (i = 0; i < TC_ROM_LLEN; i++) {
1190 		firmwr[i] = addr->firmware_rev[i].value;
1191 		vendor[i] = addr->vendor_name[i].value;
1192 		module[i] = addr->module_name[i].value;
1193 		if (i >= TC_ROM_SLEN)
1194 			continue;
1195 		host_type[i] = addr->host_firmware_type[i].value;
1196 	}
1197 
1198 	if (tc_verbose) {
1199 		firmwr[TC_ROM_LLEN] = '\0';
1200 		vendor[TC_ROM_LLEN] = '\0';
1201 		module[TC_ROM_LLEN] = '\0';
1202 		host_type[TC_ROM_SLEN] = '\0';
1203 		printf("%s %s '%s' at x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
1204 		       "Found a", vendor, module, addr,
1205 		       "Firmware rev.", firmwr,
1206 		       "diagnostics for a", host_type,
1207 		       "ROM size is", addr->rom_size.value << 3,
1208 		       "Kbytes, uses", addr->slot_size.value, "TC slot(s)");
1209 	}
1210 
1211 	bcopy(module, slot->module_name, TC_ROM_LLEN);
1212 	bcopy(vendor, slot->module_id, TC_ROM_LLEN);
1213 	bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
1214 	slot->slot_size = addr->slot_size.value;
1215 	slot->rom_width = width;
1216 
1217 	return (1);
1218 }
1219 
1220 /*
1221  * Enable/Disable interrupts for a TURBOchannel slot.
1222  */
1223 tc_enable_interrupt(slotno, on)
1224 	register int slotno;
1225 	int on;
1226 {
1227 	register volatile int *p_csr = (volatile int *)MACH_SYS_CSR_ADDR;
1228 	int csr;
1229 	int s;
1230 
1231 	slotno = 1 << (slotno + MACH_CSR_IOINTEN_SHIFT);
1232 	s = Mach_spl0();
1233 	csr = *p_csr & ~(MACH_CSR_MBZ | 0xFF);
1234 	if (on)
1235 		*p_csr = csr | slotno;
1236 	else
1237 		*p_csr = csr & ~slotno;
1238 	splx(s);
1239 }
1240 
1241 #endif /* DS5000 */
1242