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