xref: /original-bsd/sys/pmax/pmax/machdep.c (revision cda5c60b)
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.20 (Berkeley) 05/09/93
14  */
15 
16 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/signalvar.h>
21 #include <sys/kernel.h>
22 #include <sys/map.h>
23 #include <sys/proc.h>
24 #include <sys/buf.h>
25 #include <sys/reboot.h>
26 #include <sys/conf.h>
27 #include <sys/file.h>
28 #include <sys/clist.h>
29 #include <sys/callout.h>
30 #include <sys/malloc.h>
31 #include <sys/mbuf.h>
32 #include <sys/msgbuf.h>
33 #include <sys/user.h>
34 #include <sys/exec.h>
35 #ifdef SYSVSHM
36 #include <sys/shm.h>
37 #endif
38 
39 #include <vm/vm_kern.h>
40 
41 #include <machine/cpu.h>
42 #include <machine/reg.h>
43 #include <machine/psl.h>
44 #include <machine/pte.h>
45 #include <machine/dc7085cons.h>
46 
47 #include <pmax/stand/dec_prom.h>
48 
49 #include <pmax/dev/device.h>
50 #include <pmax/dev/sccreg.h>
51 #include <pmax/dev/ascreg.h>
52 
53 #include <pmax/pmax/clockreg.h>
54 #include <pmax/pmax/kn01.h>
55 #include <pmax/pmax/kn02.h>
56 #include <pmax/pmax/kmin.h>
57 #include <pmax/pmax/maxine.h>
58 #include <pmax/pmax/kn03.h>
59 #include <pmax/pmax/asic.h>
60 #include <pmax/pmax/turbochannel.h>
61 #include <pmax/pmax/pmaxtype.h>
62 #include <pmax/pmax/cons.h>
63 
64 #include <pm.h>
65 #include <cfb.h>
66 #include <mfb.h>
67 #include <xcfb.h>
68 #include <dc.h>
69 #include <dtop.h>
70 #include <scc.h>
71 #include <le.h>
72 #include <asc.h>
73 
74 #if NDC > 0
75 extern int dcGetc(), dcparam();
76 extern void dcPutc();
77 #endif
78 #if NDTOP > 0
79 extern int dtopKBDGetc();
80 #endif
81 #if NSCC > 0
82 extern int sccGetc(), sccparam();
83 extern void sccPutc();
84 #endif
85 extern int KBDGetc();
86 extern void fbPutc();
87 extern struct consdev cn_tab;
88 
89 /* Will scan from max to min, inclusive */
90 static int tc_max_slot = KN02_TC_MAX;
91 static int tc_min_slot = KN02_TC_MIN;
92 static u_int tc_slot_phys_base [TC_MAX_SLOTS] = {
93 	/* use 3max for default values */
94 	KN02_PHYS_TC_0_START, KN02_PHYS_TC_1_START,
95 	KN02_PHYS_TC_2_START, KN02_PHYS_TC_3_START,
96 	KN02_PHYS_TC_4_START, KN02_PHYS_TC_5_START,
97 	KN02_PHYS_TC_6_START, KN02_PHYS_TC_7_START
98 };
99 
100 /* the following is used externally (sysctl_hw) */
101 char	machine[] = "DEC";	/* cpu "architecture" */
102 char	cpu_model[30];
103 
104 vm_map_t buffer_map;
105 
106 /*
107  * Declare these as initialized data so we can patch them.
108  */
109 int	nswbuf = 0;
110 #ifdef	NBUF
111 int	nbuf = NBUF;
112 #else
113 int	nbuf = 0;
114 #endif
115 #ifdef	BUFPAGES
116 int	bufpages = BUFPAGES;
117 #else
118 int	bufpages = 0;
119 #endif
120 int	msgbufmapped = 0;	/* set when safe to use msgbuf */
121 int	maxmem;			/* max memory per process */
122 int	physmem;		/* max supported memory, changes to actual */
123 int	pmax_boardtype;		/* Mother board type */
124 u_long	le_iomem;		/* 128K for lance chip via. ASIC */
125 u_long	asc_iomem;		/* and 7 * 8K buffers for the scsi */
126 u_long	asic_base;		/* Base address of I/O asic */
127 const	struct callback *callv;	/* pointer to PROM entry points */
128 
129 void	(*tc_enable_interrupt)();
130 extern	int (*pmax_hardware_intr)();
131 void	pmax_slot_hand_fill();
132 int	kn02_intr(), kmin_intr(), xine_intr(), pmax_intr();
133 #ifdef DS5000_240
134 int	kn03_intr();
135 #endif
136 extern	int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3(), splhigh();
137 int	(*Mach_splnet)() = splhigh;
138 int	(*Mach_splbio)() = splhigh;
139 int	(*Mach_splimp)() = splhigh;
140 int	(*Mach_spltty)() = splhigh;
141 int	(*Mach_splclock)() = splhigh;
142 int	(*Mach_splstatclock)() = splhigh;
143 void	(*tc_slot_hand_fill)();
144 extern	volatile struct chiptime *Mach_clock_addr;
145 u_long	kmin_tc3_imask, xine_tc3_imask;
146 #ifdef DS5000_240
147 u_long	kn03_tc3_imask;
148 #endif
149 tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
150 static	void asic_init();
151 extern	void RemconsInit();
152 #ifdef DS5000
153 void	kn02_enable_intr(), kn02_slot_hand_fill(),
154 	kmin_enable_intr(), kmin_slot_hand_fill(),
155 	xine_enable_intr(), xine_slot_hand_fill(),
156 	tc_find_all_options();
157 #ifdef DS5000_240
158 void	kn03_enable_intr(), kn03_slot_hand_fill();
159 #endif
160 #endif /* DS5000 */
161 
162 /*
163  * safepri is a safe priority for sleep to set for a spin-wait
164  * during autoconfiguration or after a panic.
165  */
166 int	safepri = PSL_LOWIPL;
167 
168 struct	user *proc0paddr;
169 struct	proc nullproc;		/* for use by swtch_exit() */
170 
171 /*
172  * Do all the stuff that locore normally does before calling main().
173  * Process arguments passed to us by the prom monitor.
174  * Return the first page address following the system.
175  */
176 mach_init(argc, argv, code, cv)
177 	int argc;
178 	char *argv[];
179 	u_int code;
180 	const struct callback *cv;
181 {
182 	register char *cp;
183 	register int i;
184 	register unsigned firstaddr;
185 	register caddr_t v;
186 	caddr_t start;
187 	extern char edata[], end[];
188 	extern char MachUTLBMiss[], MachUTLBMissEnd[];
189 	extern char MachException[], MachExceptionEnd[];
190 
191 	/* clear the BSS segment */
192 	v = (caddr_t)pmax_round_page(end);
193 	bzero(edata, v - edata);
194 
195 	/* check for direct boot from DS5000 PROM */
196 	if (argc > 0 && strcmp(argv[0], "boot") == 0) {
197 		argc--;
198 		argv++;
199 	}
200 
201 	/* look at argv[0] and compute bootdev */
202 	makebootdev(argv[0]);
203 
204 	/*
205 	 * Look at arguments passed to us and compute boothowto.
206 	 */
207 #ifdef GENERIC
208 	boothowto = RB_SINGLE | RB_ASKNAME;
209 #else
210 	boothowto = RB_SINGLE;
211 #endif
212 #ifdef KADB
213 	boothowto |= RB_KDB;
214 #endif
215 	if (argc > 1) {
216 		for (i = 1; i < argc; i++) {
217 			for (cp = argv[i]; *cp; cp++) {
218 				switch (*cp) {
219 				case 'a': /* autoboot */
220 					boothowto &= ~RB_SINGLE;
221 					break;
222 
223 				case 'd': /* use compiled in default root */
224 					boothowto |= RB_DFLTROOT;
225 					break;
226 
227 				case 'm': /* mini root present in memory */
228 					boothowto |= RB_MINIROOT;
229 					break;
230 
231 				case 'n': /* ask for names */
232 					boothowto |= RB_ASKNAME;
233 					break;
234 
235 				case 'N': /* don't ask for names */
236 					boothowto &= ~RB_ASKNAME;
237 				}
238 			}
239 		}
240 	}
241 
242 #ifdef MFS
243 	/*
244 	 * Check to see if a mini-root was loaded into memory. It resides
245 	 * at the start of the next page just after the end of BSS.
246 	 */
247 	if (boothowto & RB_MINIROOT) {
248 		boothowto |= RB_DFLTROOT;
249 		v += mfs_initminiroot(v);
250 	}
251 #endif
252 
253 	/*
254 	 * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
255 	 */
256 	start = v;
257 	curproc->p_addr = proc0paddr = (struct user *)v;
258 	curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
259 	firstaddr = MACH_CACHED_TO_PHYS(v);
260 	for (i = 0; i < UPAGES; i++) {
261 		MachTLBWriteIndexed(i,
262 			(UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT),
263 			curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M);
264 		firstaddr += NBPG;
265 	}
266 	v += UPAGES * NBPG;
267 	MachSetPID(1);
268 
269 	/*
270 	 * init nullproc for swtch_exit().
271 	 * init mapping for u page(s), pm_tlbpid 0
272 	 * This could be used for an idle process.
273 	 */
274 	nullproc.p_addr = (struct user *)v;
275 	nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs;
276 	bcopy("nullproc", nullproc.p_comm, sizeof("nullproc"));
277 	for (i = 0; i < UPAGES; i++) {
278 		nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M;
279 		firstaddr += NBPG;
280 	}
281 	v += UPAGES * NBPG;
282 
283 	/* clear pages for u areas */
284 	bzero(start, v - start);
285 
286 	/*
287 	 * Copy down exception vector code.
288 	 */
289 	if (MachUTLBMissEnd - MachUTLBMiss > 0x80)
290 		panic("startup: UTLB code too large");
291 	bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC,
292 		MachUTLBMissEnd - MachUTLBMiss);
293 	bcopy(MachException, (char *)MACH_GEN_EXC_VEC,
294 		MachExceptionEnd - MachException);
295 
296 	/*
297 	 * Clear out the I and D caches.
298 	 */
299 	MachConfigCache();
300 	MachFlushCache();
301 
302 	/*
303 	 * Determine what model of computer we are running on.
304 	 */
305 	if (code == DEC_PROM_MAGIC) {
306 		callv = cv;
307 		i = (*cv->getsysid)();
308 		cp = "";
309 	} else {
310 		callv = &callvec;
311 		if (cp = (*callv->getenv)("systype"))
312 			i = atoi(cp);
313 		else {
314 			cp = "";
315 			i = 0;
316 		}
317 	}
318 	/* check for MIPS based platform */
319 	if (((i >> 24) & 0xFF) != 0x82) {
320 		printf("Unknown System type '%s' 0x%x\n", cp, i);
321 		boot(RB_HALT | RB_NOSYNC);
322 	}
323 
324 	/* check what model platform we are running on */
325 	pmax_boardtype = ((i >> 16) & 0xff);
326 	switch (pmax_boardtype) {
327 	case DS_PMAX:	/* DS3100 Pmax */
328 		/*
329 		 * Set up interrupt handling and I/O addresses.
330 		 */
331 		pmax_hardware_intr = pmax_intr;
332 		Mach_splnet = Mach_spl1;
333 		Mach_splbio = Mach_spl0;
334 		Mach_splimp = Mach_spl1;
335 		Mach_spltty = Mach_spl2;
336 		Mach_splclock = Mach_spl3;
337 		Mach_splstatclock = Mach_spl3;
338 		Mach_clock_addr = (volatile struct chiptime *)
339 			MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK);
340 		pmax_slot_hand_fill();
341 		strcpy(cpu_model, "3100");
342 		break;
343 
344 #ifdef DS5000
345 	case DS_3MAX:	/* DS5000/200 3max */
346 		{
347 		volatile int *csr_addr =
348 			(volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
349 
350 		/* disable all TURBOchannel interrupts */
351 		i = *csr_addr;
352 		*csr_addr = i & ~(KN02_CSR_WRESERVED | 0xFF);
353 
354 		tc_slot_hand_fill = kn02_slot_hand_fill;
355 		pmax_hardware_intr = kn02_intr;
356 		tc_enable_interrupt = kn02_enable_intr;
357 		Mach_splnet = Mach_spl0;
358 		Mach_splbio = Mach_spl0;
359 		Mach_splimp = Mach_spl0;
360 		Mach_spltty = Mach_spl0;
361 		Mach_splclock = Mach_spl1;
362 		Mach_splstatclock = Mach_spl1;
363 		Mach_clock_addr = (volatile struct chiptime *)
364 			MACH_PHYS_TO_UNCACHED(KN02_SYS_CLOCK);
365 
366 		/*
367 		 * Probe the TURBOchannel to see what controllers are present.
368 		 */
369 		tc_find_all_options();
370 
371 		/* clear any memory errors from probes */
372 		*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
373 		}
374 		strcpy(cpu_model, "5000/200");
375 		break;
376 
377 	case DS_3MIN:	/* DS5000/1xx 3min */
378 		tc_max_slot = KMIN_TC_MAX;
379 		tc_min_slot = KMIN_TC_MIN;
380 		tc_slot_phys_base[0] = KMIN_PHYS_TC_0_START;
381 		tc_slot_phys_base[1] = KMIN_PHYS_TC_1_START;
382 		tc_slot_phys_base[2] = KMIN_PHYS_TC_2_START;
383 		asic_base = MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
384 		tc_slot_hand_fill = kmin_slot_hand_fill;
385 		pmax_hardware_intr = kmin_intr;
386 		tc_enable_interrupt = kmin_enable_intr;
387 		kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN |
388 			KMIN_INTR_TIMEOUT);
389 
390 		/*
391 		 * Since all the motherboard interrupts come through the
392 		 * I/O ASIC, it has to be turned off for all the spls and
393 		 * since we don't know what kinds of devices are in the
394 		 * turbochannel option slots, just splhigh().
395 		 */
396 		Mach_splnet = splhigh;
397 		Mach_splbio = splhigh;
398 		Mach_splimp = splhigh;
399 		Mach_spltty = splhigh;
400 		Mach_splclock = splhigh;
401 		Mach_splstatclock = splhigh;
402 		Mach_clock_addr = (volatile struct chiptime *)
403 			MACH_PHYS_TO_UNCACHED(KMIN_SYS_CLOCK);
404 
405 		/*
406 		 * Probe the TURBOchannel to see what controllers are present.
407 		 */
408 		tc_find_all_options();
409 
410 		/*
411 		 * Initialize interrupts.
412 		 */
413 		*(u_int *)ASIC_REG_IMSK(asic_base) = KMIN_IM0;
414 		*(u_int *)ASIC_REG_INTR(asic_base) = 0;
415 		/* clear any memory errors from probes */
416 		*(unsigned *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
417 		strcpy(cpu_model, "5000/1xx");
418 		break;
419 
420 	case DS_MAXINE:	/* DS5000/xx maxine */
421 		tc_max_slot = XINE_TC_MAX;
422 		tc_min_slot = XINE_TC_MIN;
423 		tc_slot_phys_base[0] = XINE_PHYS_TC_0_START;
424 		tc_slot_phys_base[1] = XINE_PHYS_TC_1_START;
425 		asic_base = MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
426 		tc_slot_hand_fill = xine_slot_hand_fill;
427 		pmax_hardware_intr = xine_intr;
428 		tc_enable_interrupt = xine_enable_intr;
429 		Mach_splnet = Mach_spl3;
430 		Mach_splbio = Mach_spl3;
431 		Mach_splimp = Mach_spl3;
432 		Mach_spltty = Mach_spl3;
433 		Mach_splclock = Mach_spl1;
434 		Mach_splstatclock = Mach_spl1;
435 		Mach_clock_addr = (volatile struct chiptime *)
436 			MACH_PHYS_TO_UNCACHED(XINE_SYS_CLOCK);
437 
438 		/*
439 		 * Probe the TURBOchannel to see what controllers are present.
440 		 */
441 		tc_find_all_options();
442 
443 		/*
444 		 * Initialize interrupts.
445 		 */
446 		*(u_int *)ASIC_REG_IMSK(asic_base) = XINE_IM0;
447 		*(u_int *)ASIC_REG_INTR(asic_base) = 0;
448 		/* clear any memory errors from probes */
449 		*(unsigned *)MACH_PHYS_TO_UNCACHED(XINE_REG_TIMEOUT) = 0;
450 		strcpy(cpu_model, "5000/25");
451 		break;
452 
453 #ifdef DS5000_240
454 	case DS_3MAXPLUS:	/* DS5000/240 3max+ UNTESTED!! */
455 		tc_max_slot = KN03_TC_MAX;
456 		tc_min_slot = KN03_TC_MIN;
457 		tc_slot_phys_base[0] = KN03_PHYS_TC_0_START;
458 		tc_slot_phys_base[1] = KN03_PHYS_TC_1_START;
459 		tc_slot_phys_base[2] = KN03_PHYS_TC_2_START;
460 		asic_base = MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC);
461 		tc_slot_hand_fill = kn03_slot_hand_fill;
462 		pmax_hardware_intr = kn03_intr;
463 		tc_enable_interrupt = kn03_enable_intr;
464 		kn03_tc3_imask = KN03_INTR_PSWARN;
465 
466 		Mach_splnet = Mach_spl0;
467 		Mach_splbio = Mach_spl0;
468 		Mach_splimp = Mach_spl0;
469 		Mach_spltty = Mach_spl0;
470 		Mach_splclock = Mach_spl1;
471 		Mach_splstatclock = Mach_spl1;
472 		Mach_clock_addr = (volatile struct chiptime *)
473 			MACH_PHYS_TO_UNCACHED(KN03_SYS_CLOCK);
474 
475 		/*
476 		 * Probe the TURBOchannel to see what controllers are present.
477 		 */
478 		tc_find_all_options();
479 
480 		/*
481 		 * Initialize interrupts.
482 		 */
483 		*(u_int *)ASIC_REG_IMSK(asic_base) = KN03_IM0;
484 		*(u_int *)ASIC_REG_INTR(asic_base) = 0;
485 		/* clear any memory errors from probes */
486 		*(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
487 		strcpy(cpu_model, "5000/240");
488 		break;
489 #endif /* DS5000_240 */
490 #endif /* DS5000 */
491 
492 	default:
493 		printf("kernel not configured for systype 0x%x\n", i);
494 		boot(RB_HALT | RB_NOSYNC);
495 	}
496 
497 	/*
498 	 * Find out how much memory is available.
499 	 */
500 	physmem = btoc(v - KERNBASE);
501 	cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
502 	while (cp < (char *)MACH_MAX_MEM_ADDR) {
503 		if (badaddr(cp, 4))
504 			break;
505 		*(int *)cp = 0xa5a5a5a5;
506 		/*
507 		 * Data will persist on the bus if we read it right
508 		 * away. Have to be tricky here.
509 		 */
510 		((int *)cp)[4] = 0x5a5a5a5a;
511 		MachEmptyWriteBuffer();
512 		if (*(int *)cp != 0xa5a5a5a5)
513 			break;
514 		cp += NBPG;
515 		physmem++;
516 	}
517 
518 	maxmem = physmem;
519 
520 #if NLE > 0
521 	/*
522 	 * Grab 128K at the top of physical memory for the lance chip
523 	 * on machines where it does dma through the I/O ASIC.
524 	 * It must be physically contiguous and aligned on a 128K boundary.
525 	 */
526 	if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||
527 		pmax_boardtype == DS_3MAXPLUS) {
528 		maxmem -= btoc(128 * 1024);
529 		le_iomem = (maxmem << PGSHIFT);
530 	}
531 #endif /* NLE */
532 #if NASC > 0
533 	/*
534 	 * Ditto for the scsi chip. There is probably a way to make asc.c
535 	 * do dma without these buffers, but it would require major
536 	 * re-engineering of the asc driver.
537 	 * They must be 8K in size and page aligned.
538 	 */
539 	if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||
540 		pmax_boardtype == DS_3MAXPLUS) {
541 		maxmem -= btoc(ASC_NCMD * 8192);
542 		asc_iomem = (maxmem << PGSHIFT);
543 	}
544 #endif /* NASC */
545 
546 	/*
547 	 * Initialize error message buffer (at end of core).
548 	 */
549 	maxmem -= btoc(sizeof (struct msgbuf));
550 	msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT));
551 	msgbufmapped = 1;
552 
553 	/*
554 	 * Allocate space for system data structures.
555 	 * The first available kernel virtual address is in "v".
556 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
557 	 *
558 	 * These data structures are allocated here instead of cpu_startup()
559 	 * because physical memory is directly addressable. We don't have
560 	 * to map these into virtual address space.
561 	 */
562 	start = v;
563 
564 #define	valloc(name, type, num) \
565 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
566 #define	valloclim(name, type, num, lim) \
567 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
568 	valloc(cfree, struct cblock, nclist);
569 	valloc(callout, struct callout, ncallout);
570 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
571 #ifdef SYSVSHM
572 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
573 #endif
574 
575 	/*
576 	 * Determine how many buffers to allocate.
577 	 * We allocate more buffer space than the BSD standard of
578 	 * using 10% of memory for the first 2 Meg, 5% of remaining.
579 	 * We just allocate a flat 10%.  Insure a minimum of 16 buffers.
580 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
581 	 */
582 	if (bufpages == 0)
583 		bufpages = physmem / 10 / CLSIZE;
584 	if (nbuf == 0) {
585 		nbuf = bufpages;
586 		if (nbuf < 16)
587 			nbuf = 16;
588 	}
589 	if (nswbuf == 0) {
590 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
591 		if (nswbuf > 256)
592 			nswbuf = 256;		/* sanity */
593 	}
594 	valloc(swbuf, struct buf, nswbuf);
595 	valloc(buf, struct buf, nbuf);
596 
597 	/*
598 	 * Clear allocated memory.
599 	 */
600 	bzero(start, v - start);
601 
602 	/*
603 	 * Initialize the virtual memory system.
604 	 */
605 	pmap_bootstrap((vm_offset_t)v);
606 }
607 
608 /*
609  * Console initialization: called early on from main,
610  * before vm init or startup.  Do enough configuration
611  * to choose and initialize a console.
612  */
613 consinit()
614 {
615 	register int kbd, crt;
616 	register char *oscon;
617 
618 	/*
619 	 * First get the "osconsole" environment variable.
620 	 */
621 	oscon = (*callv->getenv)("osconsole");
622 	crt = kbd = -1;
623 	if (oscon && *oscon >= '0' && *oscon <= '9') {
624 		kbd = *oscon - '0';
625 		cn_tab.cn_screen = 0;
626 		while (*++oscon) {
627 			if (*oscon == ',')
628 				cn_tab.cn_screen = 1;
629 			else if (cn_tab.cn_screen &&
630 			    *oscon >= '0' && *oscon <= '9') {
631 				crt = kbd;
632 				kbd = *oscon - '0';
633 				break;
634 			}
635 		}
636 	}
637 	if (pmax_boardtype == DS_PMAX && kbd == 1)
638 		cn_tab.cn_screen = 1;
639 	/*
640 	 * The boot program uses PMAX ROM entrypoints so the ROM sets
641 	 * osconsole to '1' like the PMAX.
642 	 */
643 	if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) {
644 		cn_tab.cn_screen = 1;
645 		crt = 0;
646 		kbd = 7;
647 	}
648 
649 	/*
650 	 * First try the keyboard/crt cases then fall through to the
651 	 * remote serial lines.
652 	 */
653 	if (cn_tab.cn_screen) {
654 	    switch (pmax_boardtype) {
655 	    case DS_PMAX:
656 #if NDC > 0 && NPM > 0
657 		if (pminit()) {
658 			cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
659 			cn_tab.cn_getc = KBDGetc;
660 			cn_tab.cn_kbdgetc = dcGetc;
661 			cn_tab.cn_putc = fbPutc;
662 			cn_tab.cn_disabled = 0;
663 			return;
664 		}
665 #endif /* NDC and NPM */
666 		goto remcons;
667 
668 	    case DS_MAXINE:
669 #if NDTOP > 0
670 		if (kbd == 3) {
671 			cn_tab.cn_dev = makedev(DTOPDEV, 0);
672 			cn_tab.cn_getc = dtopKBDGetc;
673 			cn_tab.cn_putc = fbPutc;
674 		} else
675 #endif /* NDTOP */
676 			goto remcons;
677 #if NXCFB > 0
678 		if (crt == 3 && xcfbinit()) {
679 			cn_tab.cn_disabled = 0;
680 			return;
681 		}
682 #endif /* XCFB */
683 		break;
684 
685 	    case DS_3MAX:
686 #if NDC > 0
687 		if (kbd == 7) {
688 			cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
689 			cn_tab.cn_getc = KBDGetc;
690 			cn_tab.cn_kbdgetc = dcGetc;
691 			cn_tab.cn_putc = fbPutc;
692 		} else
693 #endif /* NDC */
694 			goto remcons;
695 		break;
696 
697 	    case DS_3MIN:
698 	    case DS_3MAXPLUS:
699 #if NSCC > 0
700 		if (kbd == 3) {
701 			cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT);
702 			cn_tab.cn_getc = KBDGetc;
703 			cn_tab.cn_kbdgetc = sccGetc;
704 			cn_tab.cn_putc = fbPutc;
705 		} else
706 #endif /* NSCC */
707 			goto remcons;
708 		break;
709 
710 	    default:
711 		goto remcons;
712 	    };
713 
714 	    /*
715 	     * Check for a suitable turbochannel frame buffer.
716 	     */
717 	    if (tc_slot_info[crt].driver_name) {
718 #if NMFB > 0
719 		if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&
720 		    mfbinit(tc_slot_info[crt].k1seg_address)) {
721 			cn_tab.cn_disabled = 0;
722 			return;
723 		}
724 #endif /* NMFB */
725 #if NCFB > 0
726 		if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&
727 		    cfbinit(tc_slot_info[crt].k1seg_address)) {
728 			cn_tab.cn_disabled = 0;
729 			return;
730 		}
731 #endif /* NCFB */
732 		printf("crt: %s not supported as console device\n",
733 			tc_slot_info[crt].driver_name);
734 	    } else
735 		printf("No crt console device in slot %d\n", crt);
736 	}
737 remcons:
738 	/*
739 	 * Configure a serial port as a remote console.
740 	 */
741 	cn_tab.cn_screen = 0;
742 	switch (pmax_boardtype) {
743 	case DS_PMAX:
744 #if NDC > 0
745 		if (kbd == 4)
746 			cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT);
747 		else
748 			cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
749 		cn_tab.cn_getc = dcGetc;
750 		cn_tab.cn_putc = dcPutc;
751 #endif /* NDC */
752 		break;
753 
754 	case DS_3MAX:
755 #if NDC > 0
756 		cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
757 		cn_tab.cn_getc = dcGetc;
758 		cn_tab.cn_putc = dcPutc;
759 #endif /* NDC */
760 		break;
761 
762 	case DS_3MIN:
763 	case DS_3MAXPLUS:
764 #if NSCC > 0
765 		cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT);
766 		cn_tab.cn_getc = sccGetc;
767 		cn_tab.cn_putc = sccPutc;
768 #endif /* NSCC */
769 		break;
770 
771 	case DS_MAXINE:
772 #if NSCC > 0
773 		cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT);
774 		cn_tab.cn_getc = sccGetc;
775 		cn_tab.cn_putc = sccPutc;
776 #endif /* NSCC */
777 		break;
778 	};
779 	if (cn_tab.cn_dev == NODEV)
780 		printf("Can't configure console!\n");
781 }
782 
783 /*
784  * cpu_startup: allocate memory for variable-sized tables,
785  * initialize cpu, and do autoconfiguration.
786  */
787 cpu_startup()
788 {
789 	register unsigned i;
790 	register caddr_t v;
791 	int base, residual;
792 	vm_offset_t minaddr, maxaddr;
793 	vm_size_t size;
794 #ifdef DEBUG
795 	extern int pmapdebug;
796 	int opmapdebug = pmapdebug;
797 
798 	pmapdebug = 0;
799 #endif
800 
801 	/*
802 	 * Good {morning,afternoon,evening,night}.
803 	 */
804 	printf(version);
805 	printf("real mem = %d\n", ctob(physmem));
806 
807 	/*
808 	 * Allocate virtual address space for file I/O buffers.
809 	 * Note they are different than the array of headers, 'buf',
810 	 * and usually occupy more virtual memory than physical.
811 	 */
812 	size = MAXBSIZE * nbuf;
813 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
814 				   &maxaddr, size, FALSE);
815 	minaddr = (vm_offset_t)buffers;
816 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
817 			&minaddr, size, FALSE) != KERN_SUCCESS)
818 		panic("startup: cannot allocate buffers");
819 	base = bufpages / nbuf;
820 	residual = bufpages % nbuf;
821 	for (i = 0; i < nbuf; i++) {
822 		vm_size_t curbufsize;
823 		vm_offset_t curbuf;
824 
825 		/*
826 		 * First <residual> buffers get (base+1) physical pages
827 		 * allocated for them.  The rest get (base) physical pages.
828 		 *
829 		 * The rest of each buffer occupies virtual space,
830 		 * but has no physical memory allocated for it.
831 		 */
832 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
833 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
834 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
835 		vm_map_simplify(buffer_map, curbuf);
836 	}
837 	/*
838 	 * Allocate a submap for exec arguments.  This map effectively
839 	 * limits the number of processes exec'ing at any time.
840 	 */
841 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
842 				 16 * NCARGS, TRUE);
843 	/*
844 	 * Allocate a submap for physio
845 	 */
846 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
847 				 VM_PHYS_SIZE, TRUE);
848 
849 	/*
850 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
851 	 * we use the more space efficient malloc in place of kmem_alloc.
852 	 */
853 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
854 				   M_MBUF, M_NOWAIT);
855 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
856 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
857 			       VM_MBUF_SIZE, FALSE);
858 	/*
859 	 * Initialize callouts
860 	 */
861 	callfree = callout;
862 	for (i = 1; i < ncallout; i++)
863 		callout[i-1].c_next = &callout[i];
864 	callout[i-1].c_next = NULL;
865 
866 #ifdef DEBUG
867 	pmapdebug = opmapdebug;
868 #endif
869 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
870 	printf("using %d buffers containing %d bytes of memory\n",
871 		nbuf, bufpages * CLBYTES);
872 	/*
873 	 * Set up CPU-specific registers, cache, etc.
874 	 */
875 	initcpu();
876 
877 	/*
878 	 * Set up buffers, so they can be used to read disk labels.
879 	 */
880 	bufinit();
881 
882 	/*
883 	 * Configure the system.
884 	 */
885 	configure();
886 }
887 
888 /*
889  * Set registers on exec.
890  * Clear all registers except sp, pc.
891  */
892 setregs(p, entry, retval)
893 	register struct proc *p;
894 	u_long entry;
895 	int retval[2];
896 {
897 	int sp = p->p_md.md_regs[SP];
898 	extern struct proc *machFPCurProcPtr;
899 
900 	bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
901 	p->p_md.md_regs[SP] = sp;
902 	p->p_md.md_regs[PC] = entry & ~3;
903 	p->p_md.md_regs[PS] = PSL_USERSET;
904 	p->p_md.md_flags & ~MDP_FPUSED;
905 	if (machFPCurProcPtr == p)
906 		machFPCurProcPtr = (struct proc *)0;
907 }
908 
909 /*
910  * WARNING: code in locore.s assumes the layout shown for sf_signum
911  * thru sf_handler so... don't screw with them!
912  */
913 struct sigframe {
914 	int	sf_signum;		/* signo for handler */
915 	int	sf_code;		/* additional info for handler */
916 	struct	sigcontext *sf_scp;	/* context ptr for handler */
917 	sig_t	sf_handler;		/* handler addr for u_sigc */
918 	struct	sigcontext sf_sc;	/* actual context */
919 };
920 
921 #ifdef DEBUG
922 int sigdebug = 0;
923 int sigpid = 0;
924 #define SDB_FOLLOW	0x01
925 #define SDB_KSTACK	0x02
926 #define SDB_FPSTATE	0x04
927 #endif
928 
929 /*
930  * Send an interrupt to process.
931  */
932 void
933 sendsig(catcher, sig, mask, code)
934 	sig_t catcher;
935 	int sig, mask;
936 	unsigned code;
937 {
938 	register struct proc *p = curproc;
939 	register struct sigframe *fp;
940 	register int *regs;
941 	register struct sigacts *psp = p->p_sigacts;
942 	int oonstack, fsize;
943 	struct sigcontext ksc;
944 	extern char sigcode[], esigcode[];
945 
946 	regs = p->p_md.md_regs;
947 	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
948 	/*
949 	 * Allocate and validate space for the signal handler
950 	 * context. Note that if the stack is in data space, the
951 	 * call to grow() is a nop, and the copyout()
952 	 * will fail if the process has not already allocated
953 	 * the space with a `brk'.
954 	 */
955 	fsize = sizeof(struct sigframe);
956 	if ((psp->ps_flags & SAS_ALTSTACK) &&
957 	    (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
958 	    (psp->ps_sigonstack & sigmask(sig))) {
959 		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
960 					 psp->ps_sigstk.ss_size - fsize);
961 		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
962 	} else
963 		fp = (struct sigframe *)(regs[SP] - fsize);
964 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
965 		(void)grow(p, (unsigned)fp);
966 #ifdef DEBUG
967 	if ((sigdebug & SDB_FOLLOW) ||
968 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
969 		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
970 		       p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
971 #endif
972 	/*
973 	 * Build the signal context to be used by sigreturn.
974 	 */
975 	ksc.sc_onstack = oonstack;
976 	ksc.sc_mask = mask;
977 	ksc.sc_pc = regs[PC];
978 	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */
979 	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
980 		sizeof(ksc.sc_regs) - sizeof(int));
981 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
982 	if (ksc.sc_fpused) {
983 		extern struct proc *machFPCurProcPtr;
984 
985 		/* if FPU has current state, save it first */
986 		if (p == machFPCurProcPtr)
987 			MachSaveCurFPState(p);
988 		bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
989 			sizeof(ksc.sc_fpregs));
990 	}
991 	if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
992 		/*
993 		 * Process has trashed its stack; give it an illegal
994 		 * instruction to halt it in its tracks.
995 		 */
996 		SIGACTION(p, SIGILL) = SIG_DFL;
997 		sig = sigmask(SIGILL);
998 		p->p_sigignore &= ~sig;
999 		p->p_sigcatch &= ~sig;
1000 		p->p_sigmask &= ~sig;
1001 		psignal(p, SIGILL);
1002 		return;
1003 	}
1004 	/*
1005 	 * Build the argument list for the signal handler.
1006 	 */
1007 	regs[A0] = sig;
1008 	regs[A1] = code;
1009 	regs[A2] = (int)&fp->sf_sc;
1010 	regs[A3] = (int)catcher;
1011 
1012 	regs[PC] = (int)catcher;
1013 	regs[SP] = (int)fp;
1014 	/*
1015 	 * Signal trampoline code is at base of user stack.
1016 	 */
1017 	regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
1018 #ifdef DEBUG
1019 	if ((sigdebug & SDB_FOLLOW) ||
1020 	    (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1021 		printf("sendsig(%d): sig %d returns\n",
1022 		       p->p_pid, sig);
1023 #endif
1024 }
1025 
1026 /*
1027  * System call to cleanup state after a signal
1028  * has been taken.  Reset signal mask and
1029  * stack state from context left by sendsig (above).
1030  * Return to previous pc and psl as specified by
1031  * context left by sendsig. Check carefully to
1032  * make sure that the user has not modified the
1033  * psl to gain improper priviledges or to cause
1034  * a machine fault.
1035  */
1036 struct sigreturn_args {
1037 	struct sigcontext *sigcntxp;
1038 };
1039 /* ARGSUSED */
1040 sigreturn(p, uap, retval)
1041 	struct proc *p;
1042 	struct sigreturn_args *uap;
1043 	int *retval;
1044 {
1045 	register struct sigcontext *scp;
1046 	register int *regs;
1047 	struct sigcontext ksc;
1048 	int error;
1049 
1050 	scp = uap->sigcntxp;
1051 #ifdef DEBUG
1052 	if (sigdebug & SDB_FOLLOW)
1053 		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
1054 #endif
1055 	regs = p->p_md.md_regs;
1056 	/*
1057 	 * Test and fetch the context structure.
1058 	 * We grab it all at once for speed.
1059 	 */
1060 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
1061 	if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
1062 #ifdef DEBUG
1063 		if (!(sigdebug & SDB_FOLLOW))
1064 			printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
1065 		printf("  old sp %x ra %x pc %x\n",
1066 			regs[SP], regs[RA], regs[PC]);
1067 		printf("  new sp %x ra %x pc %x err %d z %x\n",
1068 			ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
1069 			error, ksc.sc_regs[ZERO]);
1070 #endif
1071 		return (EINVAL);
1072 	}
1073 	scp = &ksc;
1074 	/*
1075 	 * Restore the user supplied information
1076 	 */
1077 	if (scp->sc_onstack & 01)
1078 		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
1079 	else
1080 		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
1081 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
1082 	regs[PC] = scp->sc_pc;
1083 	bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)&regs[1],
1084 		sizeof(scp->sc_regs) - sizeof(int));
1085 	if (scp->sc_fpused)
1086 		bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
1087 			sizeof(scp->sc_fpregs));
1088 	return (EJUSTRETURN);
1089 }
1090 
1091 int	waittime = -1;
1092 
1093 boot(howto)
1094 	register int howto;
1095 {
1096 
1097 	/* take a snap shot before clobbering any registers */
1098 	if (curproc)
1099 		savectx(curproc->p_addr, 0);
1100 
1101 #ifdef DEBUG
1102 	if (panicstr)
1103 		stacktrace();
1104 #endif
1105 
1106 	boothowto = howto;
1107 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1108 		register struct buf *bp;
1109 		int iter, nbusy;
1110 
1111 		waittime = 0;
1112 		(void) spl0();
1113 		printf("syncing disks... ");
1114 		/*
1115 		 * Release vnodes held by texts before sync.
1116 		 */
1117 		if (panicstr == 0)
1118 			vnode_pager_umount(NULL);
1119 #ifdef notdef
1120 #include "fd.h"
1121 #if NFD > 0
1122 		fdshutdown();
1123 #endif
1124 #endif
1125 		sync(&proc0, (void *)NULL, (int *)NULL);
1126 
1127 		for (iter = 0; iter < 20; iter++) {
1128 			nbusy = 0;
1129 			for (bp = &buf[nbuf]; --bp >= buf; )
1130 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
1131 					nbusy++;
1132 			if (nbusy == 0)
1133 				break;
1134 			printf("%d ", nbusy);
1135 			DELAY(40000 * iter);
1136 		}
1137 		if (nbusy)
1138 			printf("giving up\n");
1139 		else
1140 			printf("done\n");
1141 		/*
1142 		 * If we've been adjusting the clock, the todr
1143 		 * will be out of synch; adjust it now.
1144 		 */
1145 		resettodr();
1146 	}
1147 	(void) splhigh();		/* extreme priority */
1148 	if (callv != &callvec) {
1149 		if (howto & RB_HALT)
1150 			(*callv->rex)('h');
1151 		else {
1152 			if (howto & RB_DUMP)
1153 				dumpsys();
1154 			(*callv->rex)('b');
1155 		}
1156 	} else if (howto & RB_HALT) {
1157 		volatile void (*f)() = (volatile void (*)())DEC_PROM_REINIT;
1158 
1159 		(*f)();	/* jump back to prom monitor */
1160 	} else {
1161 		volatile void (*f)() = (volatile void (*)())DEC_PROM_AUTOBOOT;
1162 
1163 		if (howto & RB_DUMP)
1164 			dumpsys();
1165 		(*f)();	/* jump back to prom monitor and do 'auto' cmd */
1166 	}
1167 	/*NOTREACHED*/
1168 }
1169 
1170 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
1171 int	dumpsize = 0;		/* also for savecore */
1172 long	dumplo = 0;
1173 
1174 dumpconf()
1175 {
1176 	int nblks;
1177 
1178 	dumpsize = physmem;
1179 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
1180 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1181 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
1182 			dumpsize = btoc(dbtob(nblks - dumplo));
1183 		else if (dumplo == 0)
1184 			dumplo = nblks - btodb(ctob(physmem));
1185 	}
1186 	/*
1187 	 * Don't dump on the first CLBYTES (why CLBYTES?)
1188 	 * in case the dump device includes a disk label.
1189 	 */
1190 	if (dumplo < btodb(CLBYTES))
1191 		dumplo = btodb(CLBYTES);
1192 }
1193 
1194 /*
1195  * Doadump comes here after turning off memory management and
1196  * getting on the dump stack, either when called above, or by
1197  * the auto-restart code.
1198  */
1199 dumpsys()
1200 {
1201 	int error;
1202 
1203 	msgbufmapped = 0;
1204 	if (dumpdev == NODEV)
1205 		return;
1206 	/*
1207 	 * For dumps during autoconfiguration,
1208 	 * if dump device has already configured...
1209 	 */
1210 	if (dumpsize == 0)
1211 		dumpconf();
1212 	if (dumplo < 0)
1213 		return;
1214 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
1215 	printf("dump ");
1216 	switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
1217 
1218 	case ENXIO:
1219 		printf("device bad\n");
1220 		break;
1221 
1222 	case EFAULT:
1223 		printf("device not ready\n");
1224 		break;
1225 
1226 	case EINVAL:
1227 		printf("area improper\n");
1228 		break;
1229 
1230 	case EIO:
1231 		printf("i/o error\n");
1232 		break;
1233 
1234 	default:
1235 		printf("error %d\n", error);
1236 		break;
1237 
1238 	case 0:
1239 		printf("succeeded\n");
1240 	}
1241 }
1242 
1243 /*
1244  * Return the best possible estimate of the time in the timeval
1245  * to which tvp points.  Unfortunately, we can't read the hardware registers.
1246  * We guarantee that the time will be greater than the value obtained by a
1247  * previous call.
1248  */
1249 microtime(tvp)
1250 	register struct timeval *tvp;
1251 {
1252 	int s = splclock();
1253 	static struct timeval lasttime;
1254 
1255 	*tvp = time;
1256 #ifdef notdef
1257 	tvp->tv_usec += clkread();
1258 	while (tvp->tv_usec > 1000000) {
1259 		tvp->tv_sec++;
1260 		tvp->tv_usec -= 1000000;
1261 	}
1262 #endif
1263 	if (tvp->tv_sec == lasttime.tv_sec &&
1264 	    tvp->tv_usec <= lasttime.tv_usec &&
1265 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
1266 		tvp->tv_sec++;
1267 		tvp->tv_usec -= 1000000;
1268 	}
1269 	lasttime = *tvp;
1270 	splx(s);
1271 }
1272 
1273 initcpu()
1274 {
1275 	register volatile struct chiptime *c;
1276 	int i;
1277 
1278 	/* disable clock interrupts (until startrtclock()) */
1279 	c = Mach_clock_addr;
1280 	c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
1281 	i = c->regc;
1282 	spl0();		/* safe to turn interrupts on now */
1283 	return (i);
1284 }
1285 
1286 /*
1287  * Convert an ASCII string into an integer.
1288  */
1289 int
1290 atoi(s)
1291 	char *s;
1292 {
1293 	int c;
1294 	unsigned base = 10, d;
1295 	int neg = 0, val = 0;
1296 
1297 	if (s == 0 || (c = *s++) == 0)
1298 		goto out;
1299 
1300 	/* skip spaces if any */
1301 	while (c == ' ' || c == '\t')
1302 		c = *s++;
1303 
1304 	/* parse sign, allow more than one (compat) */
1305 	while (c == '-') {
1306 		neg = !neg;
1307 		c = *s++;
1308 	}
1309 
1310 	/* parse base specification, if any */
1311 	if (c == '0') {
1312 		c = *s++;
1313 		switch (c) {
1314 		case 'X':
1315 		case 'x':
1316 			base = 16;
1317 			break;
1318 		case 'B':
1319 		case 'b':
1320 			base = 2;
1321 			break;
1322 		default:
1323 			base = 8;
1324 		}
1325 	}
1326 
1327 	/* parse number proper */
1328 	for (;;) {
1329 		if (c >= '0' && c <= '9')
1330 			d = c - '0';
1331 		else if (c >= 'a' && c <= 'z')
1332 			d = c - 'a' + 10;
1333 		else if (c >= 'A' && c <= 'Z')
1334 			d = c - 'A' + 10;
1335 		else
1336 			break;
1337 		val *= base;
1338 		val += d;
1339 		c = *s++;
1340 	}
1341 	if (neg)
1342 		val = -val;
1343 out:
1344 	return val;
1345 }
1346 
1347 /*
1348  * Fill in the pmax addresses by hand.
1349  */
1350 static struct pmax_address {
1351 	char	*pmax_name;
1352 	char	*pmax_addr;
1353 	int	pmax_pri;
1354 } pmax_addresses[] = {
1355 	{ "pm",	(char *)MACH_PHYS_TO_CACHED(KN01_PHYS_FBUF_START),	3 },
1356 	{ "dc",	(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_DZ),		2 },
1357 	{ "le",	(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_LANCE),		1 },
1358 	{ "sii",(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_SII),		0 },
1359 	{ (char *)0, },
1360 };
1361 
1362 void
1363 pmax_slot_hand_fill()
1364 {
1365 	register struct pmax_ctlr *cp;
1366 	register struct driver *drp;
1367 	register struct pmax_address *pmap;
1368 
1369 	/*
1370 	 * Find the device driver entry and fill in the address.
1371 	 */
1372 	for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1373 		for (pmap = pmax_addresses; pmap->pmax_name; pmap++) {
1374 			if (strcmp(drp->d_name, pmap->pmax_name))
1375 				continue;
1376 			if (cp->pmax_addr == (char *)QUES) {
1377 				cp->pmax_addr = pmap->pmax_addr;
1378 				cp->pmax_pri = pmap->pmax_pri;
1379 				continue;
1380 			}
1381 		}
1382 	}
1383 }
1384 
1385 #ifdef DS5000
1386 /*
1387  * Mach Operating System
1388  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
1389  * All Rights Reserved.
1390  *
1391  * Permission to use, copy, modify and distribute this software and its
1392  * documentation is hereby granted, provided that both the copyright
1393  * notice and this permission notice appear in all copies of the
1394  * software, derivative works or modified versions, and any portions
1395  * thereof, and that both notices appear in supporting documentation.
1396  *
1397  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
1398  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1399  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1400  *
1401  * Carnegie Mellon requests users of this software to return to
1402  *
1403  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1404  *  School of Computer Science
1405  *  Carnegie Mellon University
1406  *  Pittsburgh PA 15213-3890
1407  *
1408  * any improvements or extensions that they make and grant Carnegie the
1409  * rights to redistribute these changes.
1410  */
1411 
1412 
1413 /*
1414  * Driver map: associates a device driver to an option type.
1415  * Drivers name are (arbitrarily) defined in each driver and
1416  * used in the various config tables.
1417  */
1418 struct drivers_map {
1419 	char	module_name[TC_ROM_LLEN];	/* from ROM, literally! */
1420 	char	*driver_name;			/* in bus_??_init[] tables */
1421 } tc_drivers_map[] = {
1422 	{ "KN02    ",	"dc"},		/* (*) 3max system board (with DC) */
1423 	{ "PMAD-AA ",	"le"},		/* Ether */
1424 	{ "PMAZ-AA ",	"asc"},		/* SCSI */
1425 	{ "PMAG-AA ",	"mfb"},		/* Mono Frame Buffer */
1426 	{ "PMAG-BA ",	"cfb"},		/* Color Frame Buffer */
1427 	{ "PMAG-CA ",	"ga"},		/* 2D graphic board */
1428 	{ "PMAG-DA ",	"gq"},		/* 3D graphic board (LM) */
1429 	{ "PMAG-FA ",	"gq"},		/* 3D graphic board (HE) */
1430 	{ "PMAG-DV ",	"xcfb"},	/* (*) maxine Color Frame Buffer */
1431 	{ "Z8530   ",	"scc"},		/* (*) 3min/maxine serial lines */
1432 	{ "ASIC    ",	"asic"},	/* (*) 3min/maxine DMA controller */
1433 	{ "XINE-FDC",	"fdc"},		/* (*) maxine floppy controller */
1434 	{ "DTOP    ",	"dtop"},	/* (*) maxine desktop bus */
1435 	{ "AMD79c30",	"isdn"},	/* (*) maxine ISDN chip */
1436 	{ "XINE-FRC",	"frc"},		/* (*) maxine free-running counter */
1437 	{ "", 0}			/* list end */
1438 };
1439 
1440 /*
1441  * Identify an option on the TC.  Looks at the mandatory
1442  * info in the option's ROM and checks it.
1443  */
1444 #ifdef DEBUG
1445 int tc_verbose = 0;
1446 #endif
1447 
1448 static int
1449 tc_identify_option(addr, slot, complain)
1450 	tc_rommap_t	*addr;
1451 	tc_option_t	*slot;
1452 	int		complain;
1453 {
1454 	register int	i;
1455 	unsigned char   width;
1456 	char            firmwr[TC_ROM_LLEN+1], vendor[TC_ROM_LLEN+1],
1457 			module[TC_ROM_LLEN+1], host_type[TC_ROM_SLEN+1];
1458 
1459 	/*
1460 	 * We do not really use the 'width' info, but take advantage
1461 	 * of the restriction that the spec impose on the portion
1462 	 * of the ROM that maps between +0x3e0 and +0x470, which
1463 	 * is the only piece we need to look at.
1464 	 */
1465 	width = addr->rom_width.value;
1466 	switch (width) {
1467 	case 1:
1468 	case 2:
1469 	case 4:
1470 		break;
1471 
1472 	default:
1473 #ifdef DEBUG
1474 		if (tc_verbose && complain)
1475 			printf("%s (x%x) at x%x\n", "Invalid ROM width",
1476 			       width, addr);
1477 #endif
1478 		return (0);
1479 	}
1480 
1481 	if (addr->rom_stride.value != 4) {
1482 #ifdef DEBUG
1483 		if (tc_verbose && complain)
1484 			printf("%s (x%x) at x%x\n", "Invalid ROM stride",
1485 			       addr->rom_stride.value, addr);
1486 #endif
1487 		return (0);
1488 	}
1489 
1490 	if ((addr->test_data[0] != 0x55) ||
1491 	    (addr->test_data[4] != 0x00) ||
1492 	    (addr->test_data[8] != 0xaa) ||
1493 	    (addr->test_data[12] != 0xff)) {
1494 #ifdef DEBUG
1495 		if (tc_verbose && complain)
1496 			printf("%s x%x\n", "Test pattern failed, option at",
1497 			       addr);
1498 #endif
1499 		return (0);
1500 	}
1501 
1502 	for (i = 0; i < TC_ROM_LLEN; i++) {
1503 		firmwr[i] = addr->firmware_rev[i].value;
1504 		vendor[i] = addr->vendor_name[i].value;
1505 		module[i] = addr->module_name[i].value;
1506 		if (i >= TC_ROM_SLEN)
1507 			continue;
1508 		host_type[i] = addr->host_firmware_type[i].value;
1509 	}
1510 	firmwr[TC_ROM_LLEN] = vendor[TC_ROM_LLEN] =
1511 	module[TC_ROM_LLEN] = host_type[TC_ROM_SLEN] = '\0';
1512 
1513 #ifdef DEBUG
1514 	if (tc_verbose)
1515 		printf("%s %s '%s' at 0x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
1516 		"Found a", vendor, module, addr,
1517 		"Firmware rev.", firmwr,
1518 		"diagnostics for a", host_type,
1519 		"ROM size is", addr->rom_size.value << 3,
1520 		"Kbytes, uses", addr->slot_size.value, "TC slot(s)");
1521 #endif
1522 
1523 	bcopy(module, slot->module_name, TC_ROM_LLEN);
1524 	bcopy(vendor, slot->module_id, TC_ROM_LLEN);
1525 	bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
1526 	slot->slot_size = addr->slot_size.value;
1527 	slot->rom_width = width;
1528 
1529 	return (1);
1530 }
1531 
1532 /*
1533  * TURBOchannel autoconf procedure.  Finds in one sweep what is
1534  * hanging on the bus and fills in the tc_slot_info array.
1535  * This is only the first part of the autoconf scheme, at this
1536  * time we are basically only looking for a graphics board to
1537  * use as system console (all workstations).
1538  */
1539 
1540 void
1541 tc_find_all_options()
1542 {
1543 	register int i;
1544 	u_long addr;
1545 	int found;
1546 	register tc_option_t *sl;
1547 	struct drivers_map *map;
1548 	register struct pmax_ctlr *cp;
1549 	register struct driver *drp;
1550 
1551 	/*
1552 	 * Take a look at the bus
1553 	 */
1554 	bzero(tc_slot_info, sizeof(tc_slot_info));
1555 	for (i = tc_max_slot; i >= tc_min_slot;) {
1556 		addr = MACH_PHYS_TO_UNCACHED(tc_slot_phys_base[i]);
1557 		found = tc_probe_slot(addr, &tc_slot_info[i]);
1558 
1559 		if (found) {
1560 			/*
1561 			 * Found a slot, make a note of it
1562 			 */
1563 			tc_slot_info[i].present = 1;
1564 			tc_slot_info[i].k1seg_address = addr;
1565 		}
1566 
1567 		i -= tc_slot_info[i].slot_size;
1568 	}
1569 
1570 	/*
1571 	 * Some slots (e.g. the system slot on 3max) might require
1572 	 * hand-filling.  If so, do it now.
1573 	 */
1574 	if (tc_slot_hand_fill)
1575 		(*tc_slot_hand_fill) (tc_slot_info);
1576 
1577 	/*
1578 	 * Now for each alive slot see if we have a device driver that
1579 	 * handles it.  This is done in "priority order", meaning that
1580 	 * always present devices are at higher slot numbers on all
1581 	 * current TC machines, and option slots are at lowest numbers.
1582 	 */
1583 	for (i = TC_MAX_LOGICAL_SLOTS - 1; i >= 0; i--) {
1584 		sl = &tc_slot_info[i];
1585 		if (!sl->present)
1586 			continue;
1587 		found = FALSE;
1588 		for (map = tc_drivers_map; map->driver_name; map++) {
1589 			if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
1590 				continue;
1591 			sl->driver_name = map->driver_name;
1592 			found = TRUE;
1593 			break;
1594 		}
1595 		if (!found) {
1596 			printf("%s %s %s\n",
1597 				"Cannot associate a device driver to",
1598 				sl->module_name, ". Will (try to) ignore it.");
1599 			sl->present = 0;
1600 			continue;
1601 		}
1602 
1603 		/*
1604 		 * Find the device driver entry and fill in the address.
1605 		 */
1606 		for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1607 			if (strcmp(drp->d_name, map->driver_name))
1608 				continue;
1609 			if (cp->pmax_alive)
1610 				continue;
1611 			if (cp->pmax_addr == (char *)QUES) {
1612 				cp->pmax_addr = (char *)sl->k1seg_address;
1613 				cp->pmax_pri = i;
1614 				/*
1615 				 * Only enable interrupts if there is an
1616 				 * interrupt handler for it. (e.g., PMAG-BA
1617 				 * can't disable the vertical retrace interrupt
1618 				 * and we might want to ignore it).
1619 				 */
1620 				if (drp->d_intr)
1621 					(*tc_enable_interrupt)(i, 1);
1622 				cp->pmax_alive = 1;
1623 				break;
1624 			}
1625 			if (cp->pmax_addr != (char *)sl->k1seg_address) {
1626 				cp->pmax_addr = (char *)QUES;
1627 				printf("%s: device not at configued address (expected at %x, found at %x)\n",
1628 					drp->d_name,
1629 					cp->pmax_addr, sl->k1seg_address);
1630 			}
1631 		}
1632 	}
1633 }
1634 
1635 /*
1636  * Probe a slot in the TURBOchannel. Return TRUE if a valid option
1637  * is present, FALSE otherwise. A side-effect is to fill the slot
1638  * descriptor with the size of the option, whether it is
1639  * recognized or not.
1640  */
1641 int
1642 tc_probe_slot(addr, slot)
1643 	caddr_t addr;
1644 	tc_option_t *slot;
1645 {
1646 	int i;
1647 	static unsigned tc_offset_rom[] = {
1648 		TC_OFF_PROTO_ROM, TC_OFF_ROM
1649 	};
1650 #define TC_N_OFFSETS	sizeof(tc_offset_rom)/sizeof(unsigned)
1651 
1652 	slot->slot_size = 1;
1653 
1654 	for (i = 0; i < TC_N_OFFSETS; i++) {
1655 		if (badaddr(addr + tc_offset_rom[i], 4))
1656 			continue;
1657 		/* complain only on last chance */
1658 		if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]),
1659 		    slot, i == (TC_N_OFFSETS-1)))
1660 			return (1);
1661 	}
1662 	return (0);
1663 #undef TC_N_OFFSETS
1664 }
1665 
1666 /*
1667  * Enable/Disable interrupts for a TURBOchannel slot.
1668  */
1669 void
1670 kn02_enable_intr(slotno, on)
1671 	register int slotno;
1672 	int on;
1673 {
1674 	register volatile int *p_csr =
1675 		(volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
1676 	int csr;
1677 	int s;
1678 
1679 	slotno = 1 << (slotno + KN02_CSR_IOINTEN_SHIFT);
1680 	s = Mach_spl0();
1681 	csr = *p_csr & ~(KN02_CSR_WRESERVED | 0xFF);
1682 	if (on)
1683 		*p_csr = csr | slotno;
1684 	else
1685 		*p_csr = csr & ~slotno;
1686 	splx(s);
1687 }
1688 
1689 /*
1690  *	Object:
1691  *		kmin_enable_intr		EXPORTED function
1692  *
1693  *	Enable/Disable interrupts from a TURBOchannel slot.
1694  *
1695  *	We pretend we actually have 8 slots even if we really have
1696  *	only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to
1697  *	slots 3-7 (see kmin_slot_hand_fill).
1698  */
1699 void
1700 kmin_enable_intr(slotno, on)
1701 	register unsigned int slotno;
1702 	int on;
1703 {
1704 	register unsigned mask;
1705 
1706 	switch (slotno) {
1707 	case 0:
1708 	case 1:
1709 	case 2:
1710 		return;
1711 	case KMIN_SCSI_SLOT:
1712 		mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD |
1713 			KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
1714 		break;
1715 	case KMIN_LANCE_SLOT:
1716 		mask = KMIN_INTR_LANCE;
1717 		break;
1718 	case KMIN_SCC0_SLOT:
1719 		mask = KMIN_INTR_SCC_0;
1720 		break;
1721 	case KMIN_SCC1_SLOT:
1722 		mask = KMIN_INTR_SCC_1;
1723 		break;
1724 	case KMIN_ASIC_SLOT:
1725 		mask = KMIN_INTR_ASIC;
1726 		break;
1727 	default:
1728 		return;
1729 	}
1730 	if (on)
1731 		kmin_tc3_imask |= mask;
1732 	else
1733 		kmin_tc3_imask &= ~mask;
1734 }
1735 
1736 /*
1737  *	Object:
1738  *		xine_enable_intr		EXPORTED function
1739  *
1740  *	Enable/Disable interrupts from a TURBOchannel slot.
1741  *
1742  *	We pretend we actually have 11 slots even if we really have
1743  *	only 3: TCslots 0-1 maps to slots 0-1, TCslot 2 is used for
1744  *	the system (TCslot3), TCslot3 maps to slots 3-10
1745  *	(see xine_slot_hand_fill).
1746  *	Note that all these interrupts come in via the IMR.
1747  */
1748 void
1749 xine_enable_intr(slotno, on)
1750 	register unsigned int slotno;
1751 	int on;
1752 {
1753 	register unsigned mask;
1754 
1755 	switch (slotno) {
1756 	case 0:			/* a real slot, but  */
1757 		mask = XINE_INTR_TC_0;
1758 		break;
1759 	case 1:			/* a real slot, but */
1760 		mask = XINE_INTR_TC_1;
1761 		break;
1762 	case XINE_FLOPPY_SLOT:
1763 		mask = XINE_INTR_FLOPPY;
1764 		break;
1765 	case XINE_SCSI_SLOT:
1766 		mask = (XINE_INTR_SCSI | XINE_INTR_SCSI_PTR_LOAD |
1767 			XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
1768 		break;
1769 	case XINE_LANCE_SLOT:
1770 		mask = XINE_INTR_LANCE;
1771 		break;
1772 	case XINE_SCC0_SLOT:
1773 		mask = XINE_INTR_SCC_0;
1774 		break;
1775 	case XINE_DTOP_SLOT:
1776 		mask = XINE_INTR_DTOP_RX;
1777 		break;
1778 	case XINE_ISDN_SLOT:
1779 		mask = XINE_INTR_ISDN;
1780 		break;
1781 	case XINE_ASIC_SLOT:
1782 		mask = XINE_INTR_ASIC;
1783 		break;
1784 	default:
1785 		return;/* ignore */
1786 	}
1787 	if (on)
1788 		xine_tc3_imask |= mask;
1789 	else
1790 		xine_tc3_imask &= ~mask;
1791 }
1792 
1793 #ifdef DS5000_240
1794 /*
1795  * UNTESTED!!
1796  *	Object:
1797  *		kn03_enable_intr		EXPORTED function
1798  *
1799  *	Enable/Disable interrupts from a TURBOchannel slot.
1800  *
1801  *	We pretend we actually have 8 slots even if we really have
1802  *	only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to
1803  *	slots 3-7 (see kn03_slot_hand_fill).
1804  */
1805 void
1806 kn03_enable_intr(slotno, on)
1807 	register unsigned int slotno;
1808 	int on;
1809 {
1810 	register unsigned mask;
1811 
1812 	switch (slotno) {
1813 	case 0:
1814 		mask = KN03_INTR_TC_0;
1815 		break;
1816 	case 1:
1817 		mask = KN03_INTR_TC_1;
1818 		break;
1819 	case 2:
1820 		mask = KN03_INTR_TC_2;
1821 		break;
1822 	case KN03_SCSI_SLOT:
1823 		mask = (KN03_INTR_SCSI | KN03_INTR_SCSI_PTR_LOAD |
1824 			KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
1825 		break;
1826 	case KN03_LANCE_SLOT:
1827 		mask = KN03_INTR_LANCE;
1828 		break;
1829 	case KN03_SCC0_SLOT:
1830 		mask = KN03_INTR_SCC_0;
1831 		break;
1832 	case KN03_SCC1_SLOT:
1833 		mask = KN03_INTR_SCC_1;
1834 		break;
1835 	case KN03_ASIC_SLOT:
1836 		mask = KN03_INTR_ASIC;
1837 		break;
1838 	default:
1839 		return;
1840 	}
1841 	if (on)
1842 		kn03_tc3_imask |= mask;
1843 	else
1844 		kn03_tc3_imask &= ~mask;
1845 }
1846 #endif /* DS5000_240 */
1847 
1848 /*
1849  *	Object:
1850  *		kn02_slot_hand_fill		EXPORTED function
1851  *
1852  *	Fill in by hand the info for TC slots that are non-standard.
1853  *	This is basically just the system slot on a 3max, it does not
1854  *	look to me like it follows the TC rules although some of the
1855  *	required info is indeed there.
1856  *
1857  */
1858 void
1859 kn02_slot_hand_fill(slot)
1860 	tc_option_t *slot;
1861 {
1862 	slot[7].present = 1;
1863 	slot[7].slot_size = 1;
1864 	slot[7].rom_width = 1;
1865 #if unsafe
1866 	bcopy(0xbffc0410, slot[7].module_name, TC_ROM_LLEN+1);
1867 #endif
1868 	bcopy("KN02    ", slot[7].module_name, TC_ROM_LLEN+1);
1869 	bcopy("DEC xxxx", slot[7].module_id, TC_ROM_LLEN+1);
1870 	slot[7].k1seg_address = MACH_PHYS_TO_UNCACHED(KN02_SYS_DZ);
1871 }
1872 
1873 /*
1874  *	Object:
1875  *		kmin_slot_hand_fill		EXPORTED function
1876  *
1877  *	Fill in by hand the info for TC slots that are non-standard.
1878  *	This is the system slot on a 3min, which we think of as a
1879  *	set of non-regular size TC slots.
1880  *
1881  */
1882 void
1883 kmin_slot_hand_fill(slot)
1884 	tc_option_t *slot;
1885 {
1886 	register int i;
1887 
1888 	for (i = KMIN_SCSI_SLOT; i < KMIN_ASIC_SLOT+1; i++) {
1889 		slot[i].present = 1;
1890 		slot[i].slot_size = 1;
1891 		slot[i].rom_width = 1;
1892 		slot[i].unit = 0;
1893 		bcopy("DEC KMIN", slot[i].module_id, TC_ROM_LLEN+1);
1894 	}
1895 
1896 	/* scsi */
1897 	bcopy("PMAZ-AA ", slot[KMIN_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
1898 	slot[KMIN_SCSI_SLOT].k1seg_address =
1899 		MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCSI);
1900 
1901 	/* lance */
1902 	bcopy("PMAD-AA ", slot[KMIN_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
1903 	slot[KMIN_LANCE_SLOT].k1seg_address = 0;
1904 
1905 	/* scc */
1906 	bcopy("Z8530   ", slot[KMIN_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
1907 	slot[KMIN_SCC0_SLOT].k1seg_address =
1908 		MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_0);
1909 
1910 	slot[KMIN_SCC1_SLOT].unit = 1;
1911 	bcopy("Z8530   ", slot[KMIN_SCC1_SLOT].module_name, TC_ROM_LLEN+1);
1912 	slot[KMIN_SCC1_SLOT].k1seg_address =
1913 		MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_1);
1914 
1915 	/* asic */
1916 	bcopy("ASIC    ", slot[KMIN_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
1917 	slot[KMIN_ASIC_SLOT].k1seg_address =
1918 		MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
1919 	asic_init(0);
1920 }
1921 
1922 /*
1923  *	Object:
1924  *		xine_slot_hand_fill		EXPORTED function
1925  *
1926  *	Fill in by hand the info for TC slots that are non-standard.
1927  *	This is the system slot on a 3min, which we think of as a
1928  *	set of non-regular size TC slots.
1929  *
1930  */
1931 void
1932 xine_slot_hand_fill(slot)
1933 	tc_option_t *slot;
1934 {
1935 	register int i;
1936 
1937 	for (i = XINE_FLOPPY_SLOT; i < XINE_FRC_SLOT+1; i++) {
1938 		slot[i].present = 1;
1939 		slot[i].slot_size = 1;
1940 		slot[i].rom_width = 1;
1941 		slot[i].unit = 0;
1942 		bcopy("DEC XINE", slot[i].module_id, TC_ROM_LLEN+1);
1943 	}
1944 
1945 	/* floppy */
1946 	bcopy("XINE-FDC", slot[XINE_FLOPPY_SLOT].module_name, TC_ROM_LLEN+1);
1947 	slot[XINE_FLOPPY_SLOT].k1seg_address =
1948 		MACH_PHYS_TO_UNCACHED(XINE_SYS_FLOPPY);
1949 
1950 	/* scsi */
1951 	bcopy("PMAZ-AA ", slot[XINE_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
1952 	slot[XINE_SCSI_SLOT].k1seg_address =
1953 		MACH_PHYS_TO_UNCACHED(XINE_SYS_SCSI);
1954 
1955 	/* lance */
1956 	bcopy("PMAD-AA ", slot[XINE_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
1957 	slot[XINE_LANCE_SLOT].k1seg_address =
1958 		MACH_PHYS_TO_UNCACHED(XINE_SYS_LANCE);
1959 
1960 	/* scc */
1961 	bcopy("Z8530   ", slot[XINE_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
1962 	slot[XINE_SCC0_SLOT].k1seg_address =
1963 		MACH_PHYS_TO_UNCACHED(XINE_SYS_SCC_0);
1964 
1965 	/* Desktop */
1966 	bcopy("DTOP    ", slot[XINE_DTOP_SLOT].module_name, TC_ROM_LLEN+1);
1967 	slot[XINE_DTOP_SLOT].k1seg_address =
1968 		MACH_PHYS_TO_UNCACHED(XINE_SYS_DTOP+0x20000); /* why? */
1969 
1970 	/* ISDN */
1971 	bcopy("AMD79c30", slot[XINE_ISDN_SLOT].module_name, TC_ROM_LLEN+1);
1972 	slot[XINE_ISDN_SLOT].k1seg_address =
1973 		MACH_PHYS_TO_UNCACHED(XINE_SYS_ISDN);
1974 
1975 	/* Video */
1976 	bcopy("PMAG-DV ", slot[XINE_CFB_SLOT].module_name, TC_ROM_LLEN+1);
1977 	slot[XINE_CFB_SLOT].k1seg_address =
1978 		MACH_PHYS_TO_CACHED(XINE_PHYS_CFB_START);
1979 
1980 	/* asic */
1981 	bcopy("ASIC    ", slot[XINE_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
1982 	slot[XINE_ASIC_SLOT].k1seg_address =
1983 		MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
1984 
1985 	/* free-running counter (high resolution mapped time) */
1986 	bcopy("XINE-FRC", slot[XINE_FRC_SLOT].module_name, TC_ROM_LLEN+1);
1987 	slot[XINE_FRC_SLOT].k1seg_address =
1988 		MACH_PHYS_TO_UNCACHED(XINE_REG_FCTR);
1989 	asic_init(1);
1990 }
1991 
1992 #ifdef DS5000_240
1993 /*
1994  * UNTESTED!!
1995  *	Object:
1996  *		kn03_slot_hand_fill		EXPORTED function
1997  *
1998  *	Fill in by hand the info for TC slots that are non-standard.
1999  *	This is the system slot on a 3max+, which we think of as a
2000  *	set of non-regular size TC slots.
2001  *
2002  */
2003 void
2004 kn03_slot_hand_fill(slot)
2005 	tc_option_t *slot;
2006 {
2007 	register int i;
2008 
2009 	for (i = KN03_SCSI_SLOT; i < KN03_ASIC_SLOT+1; i++) {
2010 		slot[i].present = 1;
2011 		slot[i].slot_size = 1;
2012 		slot[i].rom_width = 1;
2013 		slot[i].unit = 0;
2014 		bcopy("DEC KN03", slot[i].module_id, TC_ROM_LLEN+1);
2015 	}
2016 
2017 	/* scsi */
2018 	bcopy("PMAZ-AA ", slot[KN03_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
2019 	slot[KN03_SCSI_SLOT].k1seg_address =
2020 		MACH_PHYS_TO_UNCACHED(KN03_SYS_SCSI);
2021 
2022 	/* lance */
2023 	bcopy("PMAD-AA ", slot[KN03_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
2024 	slot[KN03_LANCE_SLOT].k1seg_address = 0;
2025 
2026 	/* scc */
2027 	bcopy("Z8530   ", slot[KN03_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
2028 	slot[KN03_SCC0_SLOT].k1seg_address =
2029 		MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_0);
2030 
2031 	slot[KN03_SCC1_SLOT].unit = 1;
2032 	bcopy("Z8530   ", slot[KN03_SCC1_SLOT].module_name, TC_ROM_LLEN+1);
2033 	slot[KN03_SCC1_SLOT].k1seg_address =
2034 		MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_1);
2035 
2036 	/* asic */
2037 	bcopy("ASIC    ", slot[KN03_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
2038 	slot[KN03_ASIC_SLOT].k1seg_address =
2039 		MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC);
2040 	asic_init(0);
2041 }
2042 #endif /* DS5000_240 */
2043 
2044 /*
2045  * Initialize the I/O asic
2046  */
2047 static void
2048 asic_init(isa_maxine)
2049 	int isa_maxine;
2050 {
2051 	volatile u_int *decoder;
2052 
2053 	/* These are common between 3min and maxine */
2054 	decoder = (volatile u_int *)ASIC_REG_LANCE_DECODE(asic_base);
2055 	*decoder = KMIN_LANCE_CONFIG;
2056 }
2057 #endif /* DS5000 */
2058