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