xref: /netbsd/sys/arch/algor/algor/machdep.c (revision c4a72b64)
1 /*	$NetBSD: machdep.c,v 1.16 2002/08/25 20:21:33 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Copyright (c) 1988 University of Utah.
41  * Copyright (c) 1992, 1993
42  *	The Regents of the University of California.  All rights reserved.
43  *
44  * This code is derived from software contributed to Berkeley by
45  * the Systems Programming Group of the University of Utah Computer
46  * Science Department, The Mach Operating System project at
47  * Carnegie-Mellon University and Ralph Campbell.
48  *
49  * Redistribution and use in source and binary forms, with or without
50  * modification, are permitted provided that the following conditions
51  * are met:
52  * 1. Redistributions of source code must retain the above copyright
53  *    notice, this list of conditions and the following disclaimer.
54  * 2. Redistributions in binary form must reproduce the above copyright
55  *    notice, this list of conditions and the following disclaimer in the
56  *    documentation and/or other materials provided with the distribution.
57  * 3. All advertising materials mentioning features or use of this software
58  *    must display the following acknowledgement:
59  *	This product includes software developed by the University of
60  *	California, Berkeley and its contributors.
61  * 4. Neither the name of the University nor the names of its contributors
62  *    may be used to endorse or promote products derived from this software
63  *    without specific prior written permission.
64  *
65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75  * SUCH DAMAGE.
76  *
77  *	@(#)machdep.c   8.3 (Berkeley) 1/12/94
78  *	from: Utah Hdr: machdep.c 1.63 91/04/24
79  */
80 
81 #include "opt_algor_p4032.h"
82 #include "opt_algor_p5064.h"
83 #include "opt_algor_p6032.h"
84 
85 #include "opt_ddb.h"
86 #include "opt_kgdb.h"
87 
88 #include "opt_memsize.h"
89 #include "opt_ethaddr.h"
90 
91 #include <sys/param.h>
92 #include <sys/systm.h>
93 #include <sys/kernel.h>
94 #include <sys/buf.h>
95 #include <sys/reboot.h>
96 #include <sys/user.h>
97 #include <sys/mount.h>
98 #include <sys/kcore.h>
99 #include <sys/boot_flag.h>
100 #include <sys/termios.h>
101 
102 #include <net/if.h>
103 #include <net/if_ether.h>
104 
105 #include <uvm/uvm_extern.h>
106 
107 #include <dev/cons.h>
108 
109 #ifdef DDB
110 #include <machine/db_machdep.h>
111 #include <ddb/db_extern.h>
112 #endif
113 
114 #include <machine/bus.h>
115 #include <machine/autoconf.h>
116 #include <machine/pmon.h>
117 
118 #include <algor/pci/vtpbcvar.h>
119 
120 #include "com.h"
121 #if NCOM > 0
122 #include <dev/ic/comreg.h>
123 #include <dev/ic/comvar.h>
124 
125 int	comcnrate = TTYDEF_SPEED;
126 #endif /* NCOM > 0 */
127 
128 #if defined(ALGOR_P4032) + \
129     defined(ALGOR_P5064) + \
130     defined(ALGOR_P6032) + \
131     0 != 1
132 #error Must configure exactly one platform.
133 #endif
134 
135 #ifdef ALGOR_P4032
136 #include <algor/algor/algor_p4032reg.h>
137 #include <algor/algor/algor_p4032var.h>
138 struct p4032_config p4032_configuration;
139 #endif
140 
141 #ifdef ALGOR_P5064
142 #include <algor/algor/algor_p5064reg.h>
143 #include <algor/algor/algor_p5064var.h>
144 struct p5064_config p5064_configuration;
145 #endif
146 
147 #ifdef ALGOR_P6032
148 #include <algor/algor/algor_p6032reg.h>
149 #include <algor/algor/algor_p6032var.h>
150 struct p6032_config p6032_configuration;
151 #endif
152 
153 /* The following are used externally (sysctl_hw). */
154 extern char	cpu_model[];
155 
156 struct	user *proc0paddr;
157 
158 /* Our exported CPU info; we can have only one. */
159 struct cpu_info cpu_info_store;
160 
161 /* Maps for VM objects. */
162 struct vm_map *exec_map = NULL;
163 struct vm_map *mb_map = NULL;
164 struct vm_map *phys_map = NULL;
165 
166 int	physmem;		/* # pages of physical memory */
167 int	maxmem;			/* max memory per process */
168 
169 int	mem_cluster_cnt;
170 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
171 
172 char	algor_ethaddr[ETHER_ADDR_LEN];
173 
174 void	mach_init(int, char *[], char *[]);	/* XXX */
175 
176 int	cpuspeed = 150;		/* XXX XXX XXX */
177 
178 void
179 mach_init(int argc, char *argv[], char *envp[])
180 {
181 	extern char kernel_text[], edata[], end[];
182 	vaddr_t kernstart, kernend;
183 	paddr_t kernstartpfn, kernendpfn, pfn0, pfn1;
184 	vsize_t size;
185 	const char *cp;
186 	char *cp0;
187 	caddr_t v;
188 	int i;
189 
190 	/* Disable interrupts. */
191 	(void) splhigh();
192 
193 	/*
194 	 * First, find the start and end of the kernel and clear
195 	 * the BSS segment.  Account for a bit of space for the
196 	 * bootstrap stack.
197 	 */
198 	led_display('b', 's', 's', ' ');
199 	kernstart = (vaddr_t) mips_trunc_page(kernel_text) - 2 * NBPG;
200 	kernend   = (vaddr_t) mips_round_page(end);
201 	memset(edata, 0, kernend - (vaddr_t)edata);
202 
203 	/*
204 	 * Initialize PAGE_SIZE-dependent variables.
205 	 */
206 	led_display('p', 'g', 's', 'z');
207 	uvm_setpagesize();
208 
209 	kernstartpfn = atop(MIPS_KSEG0_TO_PHYS(kernstart));
210 	kernendpfn   = atop(MIPS_KSEG0_TO_PHYS(kernend));
211 
212 	/*
213 	 * Initialize bus space tags and bring up the console.
214 	 */
215 #if defined(ALGOR_P4032)
216 	    {
217 		struct p4032_config *acp = &p4032_configuration;
218 		struct vtpbc_config *vt = &vtpbc_configuration;
219 		bus_space_handle_t sh;
220 
221 		strcpy(cpu_model, "Algorithmics P-4032");
222 
223 		vt->vt_addr = MIPS_PHYS_TO_KSEG1(P4032_V962PBC);
224 		vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P4032_PCICFG);
225 		vt->vt_adbase = 11;
226 
227 		led_display('v', '9', '6', '2');
228 		vtpbc_init(&acp->ac_pc, vt);
229 
230 		led_display('l', 'i', 'o', ' ');
231 		algor_p4032loc_bus_io_init(&acp->ac_lociot, acp);
232 
233 		led_display('i', 'o', ' ', ' ');
234 		algor_p4032_bus_io_init(&acp->ac_iot, acp);
235 
236 		led_display('m', 'e', 'm', ' ');
237 		algor_p4032_bus_mem_init(&acp->ac_memt, acp);
238 
239 		led_display('d', 'm', 'a', ' ');
240 		algor_p4032_dma_init(acp);
241 #if NCOM > 0
242 		/*
243 		 * Delay to allow firmware putchars to complete.
244 		 * FIFO depth * character time.
245 		 * character time = (1000000 / (defaultrate / 10))
246 		 */
247 		led_display('c', 'o', 'n', 's');
248 		DELAY(160000000 / comcnrate);
249 		if (comcnattach(&acp->ac_lociot, P4032_COM1, comcnrate,
250 		    COM_FREQ,
251 		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
252 			panic("p4032: unable to initialize serial console");
253 #else
254 		panic("p4032: not configured to use serial console");
255 #endif /* NCOM > 0 */
256 
257 		led_display('h', 'z', ' ', ' ');
258 		bus_space_map(&acp->ac_lociot, P4032_RTC, 2, 0, &sh);
259 		algor_p4032_cal_timer(&acp->ac_lociot, sh);
260 		bus_space_unmap(&acp->ac_lociot, sh, 2);
261 	    }
262 #elif defined(ALGOR_P5064)
263 	    {
264 		struct p5064_config *acp = &p5064_configuration;
265 		struct vtpbc_config *vt = &vtpbc_configuration;
266 		bus_space_handle_t sh;
267 
268 		strcpy(cpu_model, "Algorithmics P-5064");
269 
270 		vt->vt_addr = MIPS_PHYS_TO_KSEG1(P5064_V360EPC);
271 		vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P5064_PCICFG);
272 		vt->vt_adbase = 24;
273 
274 		led_display('v', '3', '6', '0');
275 		vtpbc_init(&acp->ac_pc, vt);
276 
277 		led_display('i', 'o', ' ', ' ');
278 		algor_p5064_bus_io_init(&acp->ac_iot, acp);
279 
280 		led_display('m', 'e', 'm', ' ');
281 		algor_p5064_bus_mem_init(&acp->ac_memt, acp);
282 
283 		led_display('d', 'm', 'a', ' ');
284 		algor_p5064_dma_init(acp);
285 #if NCOM > 0
286 		/*
287 		 * Delay to allow firmware putchars to complete.
288 		 * FIFO depth * character time.
289 		 * character time = (1000000 / (defaultrate / 10))
290 		 */
291 		led_display('c', 'o', 'n', 's');
292 		DELAY(160000000 / comcnrate);
293 		if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
294 		    COM_FREQ,
295 		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
296 			panic("p5064: unable to initialize serial console");
297 #else
298 		panic("p5064: not configured to use serial console");
299 #endif /* NCOM > 0 */
300 
301 		led_display('h', 'z', ' ', ' ');
302 		bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
303 		algor_p5064_cal_timer(&acp->ac_iot, sh);
304 		bus_space_unmap(&acp->ac_iot, sh, 2);
305 	    }
306 #elif defined(ALGOR_P6032)
307 	    {
308 		struct p6032_config *acp = &p6032_configuration;
309 		struct bonito_config *bc = &acp->ac_bonito;
310 		bus_space_handle_t sh;
311 
312 		strcpy(cpu_model, "Algorithmics P-6032");
313 
314 		bc->bc_adbase = 11;
315 
316 		led_display('b','n','t','o');
317 		bonito_pci_init(&acp->ac_pc, bc);
318 
319 		led_display('i','o',' ',' ');
320 		algor_p6032_bus_io_init(&acp->ac_iot, acp);
321 
322 		led_display('m','e','m',' ');
323 		algor_p6032_bus_mem_init(&acp->ac_memt, acp);
324 
325 		led_display('d','m','a',' ');
326 		algor_p6032_dma_init(acp);
327 #if NCOM > 0
328 		/*
329 		 * Delay to allow firmware putchars to complete.
330 		 * FIFO depth * character time.
331 		 * character time = (1000000 / (defaultrate / 10))
332 		 */
333 		led_display('c','o','n','s');
334 		DELAY(160000000 / comcnrate);
335 		if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
336 		    COM_FREQ,
337 		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
338 			panic("p6032: unable to initialize serial console");
339 #else
340 		panic("p6032: not configured to use serial console");
341 #endif /* NCOM > 0 */
342 
343 		led_display('h','z',' ',' ');
344 		bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
345 		algor_p6032_cal_timer(&acp->ac_iot, sh);
346 		bus_space_unmap(&acp->ac_iot, sh, 2);
347 	    }
348 #endif /* ALGOR_P4032 || ALGOR_P5064 || ALGOR_P6032 */
349 
350 	/*
351 	 * The Algorithmics boards have PMON firmware; set up our
352 	 * PMON state.
353 	 */
354 	led_display('p', 'm', 'o', 'n');
355 	pmon_init(envp);
356 
357 	/*
358 	 * Get the Ethernet address of the on-board Ethernet.
359 	 */
360 #if defined(ETHADDR)
361 	cp = ETHADDR;
362 #else
363 	cp = pmon_getenv("ethaddr");
364 #endif
365 	if (cp != NULL) {
366 		for (i = 0; i < ETHER_ADDR_LEN; i++) {
367 			algor_ethaddr[i] = strtoul(cp, &cp0, 16);
368 			cp = cp0 + 1;
369 		}
370 	}
371 
372 	/*
373 	 * Get the boot options.
374 	 */
375 	led_display('b', 'o', 'p', 't');
376 	boothowto = 0;
377 	if (argc > 1) {
378 		for (cp = argv[1]; cp != NULL && *cp != '\0'; cp++) {
379 			switch (*cp) {
380 #if defined(KGDB) || defined(DDB)
381 			case 'd':	/* break into kernel debugger */
382 				boothowto |= RB_KDB;
383 				break;
384 #endif
385 
386 			case 'h':	/* always halt, never reboot */
387 				boothowto |= RB_HALT;
388 				break;
389 
390 			case 'n':	/* askname */
391 				boothowto |= RB_ASKNAME;
392 				break;
393 
394 			case 's':	/* single-user mode */
395 				boothowto |= RB_SINGLE;
396 				break;
397 
398 			case 'q':	/* quiet boot */
399 				boothowto |= AB_QUIET;
400 				break;
401 
402 			case 'v':	/* verbose boot */
403 				boothowto |= AB_VERBOSE;
404 				break;
405 
406 			case '-':
407 				/*
408 				 * Just ignore this.  It's not required,
409 				 * but it's common for it to be passed
410 				 * regardless.
411 				 */
412 				break;
413 
414 			default:
415 				printf("Unrecognized boto flag '%c'.\n", *cp);
416 				break;
417 			}
418 		}
419 	}
420 
421 	/*
422 	 * Determine the memory size.  Use the `memsize' PMON
423 	 * variable.  If that's not available, panic.
424 	 *
425 	 * Note: Reserve the first page!  That's where the trap
426 	 * vectors are located.
427 	 */
428 #if defined(MEMSIZE)
429 	size = MEMSIZE;
430 #else
431 	if ((cp = pmon_getenv("memsize")) != NULL)
432 		size = strtoul(cp, NULL, 0);
433 	else {
434 		printf("FATAL: `memsize' PMON variable not set.  Set it to\n");
435 		printf("       the amount of memory (in MB) and try again.\n");
436 		printf("       Or, build a kernel with the `MEMSIZE' "
437 		    "option.\n");
438 		panic("algor_init");
439 	}
440 #endif /* MEMSIZE */
441 	/*
442 	 * Deal with 2 different conventions of the contents
443 	 * of the memsize variable -- if it's > 1024, assume
444 	 * it's already in bytes, not megabytes.
445 	 */
446 	if (size < 1024) {
447 		printf("Memory size: 0x%08lx (0x%08lx)\n", size * 1024 * 1024,
448 		    size);
449 		size *= 1024 * 1024;
450 	} else
451 		printf("Memory size: 0x%08lx\n", size);
452 
453 	mem_clusters[mem_cluster_cnt].start = NBPG;
454 	mem_clusters[mem_cluster_cnt].size =
455 	    size - mem_clusters[mem_cluster_cnt].start;
456 	mem_cluster_cnt++;
457 
458 	/*
459 	 * Copy the exception-dispatch code down to the exception vector.
460 	 * Initialize the locore function vector.  Clear out the I- and
461 	 * D-caches.
462 	 *
463 	 * We can no longer call into PMON after this.
464 	 */
465 	led_display('v', 'e', 'c', 'i');
466 	mips_vector_init();
467 
468 	/*
469 	 * Load the physical memory clusters into the VM system.
470 	 */
471 	led_display('v', 'm', 'p', 'g');
472 	for (i = 0; i < mem_cluster_cnt; i++) {
473 		physmem += atop(mem_clusters[i].size);
474 		pfn0 = atop(mem_clusters[i].start);
475 		pfn1 = pfn0 + atop(mem_clusters[i].size);
476 		if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) {
477 			/*
478 			 * Must compute the location of the kernel
479 			 * within the segment.
480 			 */
481 #if 1
482 			printf("Cluster %d contains kernel\n", i);
483 #endif
484 			if (pfn0 < kernstartpfn) {
485 				/*
486 				 * There is a chunk before the kernel.
487 				 */
488 #if 1
489 				printf("Loading chunk before kernel: "
490 				    "0x%lx / 0x%lx\n", pfn0, kernstartpfn);
491 #endif
492 				uvm_page_physload(pfn0, kernstartpfn,
493 				    pfn0, kernstartpfn, VM_FREELIST_DEFAULT);
494 			}
495 			if (kernendpfn < pfn1) {
496 				/*
497 				 * There is a chunk after the kernel.
498 				 */
499 #if 1
500 				printf("Loading chunk after kernel: "
501 				    "0x%lx / 0x%lx\n", kernendpfn, pfn1);
502 #endif
503 				uvm_page_physload(kernendpfn, pfn1,
504 				    kernendpfn, pfn1, VM_FREELIST_DEFAULT);
505 			}
506 		} else {
507 			/*
508 			 * Just load this cluster as one chunk.
509 			 */
510 #if 1
511 			printf("Loading cluster %d: 0x%lx / 0x%lx\n", i,
512 			    pfn0, pfn1);
513 #endif
514 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1,
515 			    VM_FREELIST_DEFAULT);
516 		}
517 	}
518 
519 	if (physmem == 0)
520 		panic("can't happen: system seems to have no memory!");
521 	maxmem = physmem;
522 
523 	/*
524 	 * Initialize message buffer (at end of core).
525 	 */
526 	mips_init_msgbuf();
527 
528 	/*
529 	 * Compute the size of system data structures.  pmap_bootstrap()
530 	 * needs some of this information.
531 	 */
532 	size = (vsize_t) allocsys(NULL, NULL);
533 
534 	/*
535 	 * Initialize the virtual memory system.
536 	 */
537 	led_display('p', 'm', 'a', 'p');
538 	pmap_bootstrap();
539 
540 	/*
541 	 * Init mapping for u page(s) for proc0.
542 	 */
543 	led_display('u', 's', 'p', 'c');
544 	v = (caddr_t) uvm_pageboot_alloc(USPACE);
545 	proc0.p_addr = proc0paddr = (struct user *) v;
546 	proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1;
547 	curpcb = &proc0.p_addr->u_pcb;
548 	curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */
549 
550 	/*
551 	 * Allocate space for system data structures.  These data structures
552 	 * are allocated here instead of cpu_startup() because physical
553 	 * memory is directly addressable.  We don't have to map these into
554 	 * the virtual address space.
555 	 */
556 	v = (caddr_t) uvm_pageboot_alloc(size);
557 	if ((allocsys(v, NULL) - v) != size)
558 		panic("mach_init: table size inconsistency");
559 
560 	/*
561 	 * Initialize debuggers, and break into them, if appropriate.
562 	 */
563 #if defined(DDB)
564 	/*
565 	 * XXX Loader doesn't give us symbols the way we like.  Need
566 	 * XXX dbsym(1) support for ELF.
567 	 */
568 	ddb_init(0, 0, 0);
569 #endif
570 
571 	if (boothowto & RB_KDB) {
572 #if defined(DDB)
573 		Debugger();
574 #endif
575 	}
576 }
577 
578 void
579 consinit(void)
580 {
581 
582 	/*
583 	 * Everything related to console initialization is done
584 	 * in mach_init().
585 	 */
586 	led_display('N', 'B', 'S', 'D');
587 }
588 
589 void
590 cpu_startup(void)
591 {
592 	vsize_t size;
593 	u_int i, base, residual;
594 	vaddr_t minaddr, maxaddr;
595 	char pbuf[9];
596 #ifdef DEBUG
597 	extern int pmapdebug;
598 	int opmapdebug = pmapdebug;
599 
600 	pmapdebug = 0;		/* Shut up pmap debug during bootstrap */
601 #endif
602 
603 	/*
604 	 * Good {morning,afternoon,evening,night}.
605 	 */
606 	printf(version);
607 	printf("%s\n", cpu_model);
608 	format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
609 	printf("total memory = %s\n", pbuf);
610 
611 	/*
612 	 * Virtual memory is bootstrapped -- notify the bus spaces
613 	 * that memory allocation is now safe.
614 	 */
615 #if defined(ALGOR_P4032)
616 	    {
617 		struct p4032_config *acp = &p4032_configuration;
618 
619 		acp->ac_mallocsafe = 1;
620 	    }
621 #elif defined(ALGOR_P5064)
622 	    {
623 		struct p5064_config *acp = &p5064_configuration;
624 
625 		acp->ac_mallocsafe = 1;
626 	    }
627 #elif defined(ALGOR_P6032)
628 	    {
629 		struct p6032_config *acp = &p6032_configuration;
630 
631 		acp->ac_mallocsafe = 1;
632 	    }
633 #endif
634 
635 	/*
636 	 * Allocate virtual address space for file I/O buffers.
637 	 * Note they are different than the array of headers, 'buf',
638 	 * and usually occupy more virtual memory than physical.
639 	 */
640 	size = MAXBSIZE * nbuf;
641 	if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
642 		    NULL, UVM_UNKNOWN_OFFSET, 0,
643 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
644 				UVM_ADV_NORMAL, 0)) != 0)
645 		panic("cpu_startup: cannot allocate VM for buffers");
646 	base = bufpages / nbuf;
647 	residual = bufpages % nbuf;
648 	for (i = 0; i < nbuf; i++) {
649 		vsize_t curbufsize;
650 		vaddr_t curbuf;
651 		struct vm_page *pg;
652 
653 		/*
654 		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
655 		 * that MAXBSIZE space, we allocate and map (base+1) pages
656 		 * for the first "residual" buffers, and then we allocate
657 		 * "base" pages for the rest.
658 		 */
659 		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
660 		curbufsize = NBPG * ((i < residual) ? (base+1) : base);
661 
662 		while (curbufsize) {
663 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
664 			if (pg == NULL)
665 				panic("cpu_startup: not enough memory for "
666 				    "buffer cache");
667 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
668 			    VM_PROT_READ|VM_PROT_WRITE);
669 			curbuf += PAGE_SIZE;
670 			curbufsize -= PAGE_SIZE;
671 		}
672 	}
673 	pmap_update(pmap_kernel());
674 
675 	/*
676 	 * Allocate a submap for exec arguments.  This map effectively
677 	 * limits the number of processes exec'ing at any time.
678 	 */
679 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
680 	    16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
681 
682 	/*
683 	 * Allocate a submap for physio.
684 	 */
685 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
686 	    VM_PHYS_SIZE, 0, FALSE, NULL);
687 
688 	/*
689 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
690 	 * are allocate via the pool allocator, and we use KSEG0 to
691 	 * map those pages.
692 	 */
693 
694 #ifdef DEBUG
695 	pmapdebug = opmapdebug;
696 #endif
697 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
698 	printf("avail memory = %s\n", pbuf);
699 	format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
700 	printf("using %u buffers containing %s of memory\n", nbuf, pbuf);
701 
702 	/*
703 	 * Set up buffers, so they can be used to read disklabels.
704 	 */
705 	bufinit();
706 }
707 
708 int	waittime = -1;
709 struct user dumppcb;	/* Actually, struct pcb would do. */
710 
711 void
712 cpu_reboot(int howto, char *bootstr)
713 {
714 	int tmp;
715 
716 	/* Take a snapshot before clobbering any registers. */
717 	if (curproc)
718 		savectx((struct user *) curpcb);
719 
720 	/* If "always halt" was specified as a boot flag, obey. */
721 	if (boothowto & RB_HALT)
722 		howto |= RB_HALT;
723 
724 	boothowto = howto;
725 
726 	/* If system is cold, just halt. */
727 	if (cold) {
728 		boothowto |= RB_HALT;
729 		goto haltsys;
730 	}
731 
732 	if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
733 		waittime = 0;
734 		vfs_shutdown();
735 		/*
736 		 * If we've been adjusting the clock, the todr
737 		 * will be out of synch; adjust it now.
738 		 */
739 		resettodr();
740 	}
741 
742 	/* Disable interrupts. */
743 	(void) splhigh();
744 
745 	if (boothowto & RB_DUMP)
746 		dumpsys();
747 
748  haltsys:
749 	/* Run any shutdown hooks. */
750 	doshutdownhooks();
751 
752 	if (boothowto & RB_HALT) {
753 		printf("\n");
754 		printf("The operating system has halted.\n");
755 		printf("Please press any key to return to the monitor.\n\n");
756 		led_display('h','a','l','t');
757 		cnpollc(1);
758 		(void) cngetc();
759 		cnpollc(0);
760 	}
761 
762 	printf("Returning to the monitor...\n\n");
763 	led_display('r', 'v', 'e', 'c');
764 	/* Jump to the reset vector. */
765 	__asm __volatile("li %0, 0xbfc00000; jr %0; nop"
766 		: "=r" (tmp)
767 		: /* no inputs */
768 		: "memory");
769 	led_display('R', 'S', 'T', 'F');
770 	for (;;)
771 		/* spin forever */ ;
772 }
773 
774 /*
775  * XXX This shouldn't be here -- it should be done w/ devprops,
776  * XXX but we don't have those yet.
777  */
778 int
779 algor_get_ethaddr(struct pci_attach_args *pa, u_int8_t *buf)
780 {
781 
782 #if defined(ALGOR_P4032)
783 	if (pa->pa_bus != 0 || pa->pa_device != 5 || pa->pa_function != 0)
784 		return (0);
785 #elif defined(ALGOR_P5064)
786 	if (pa->pa_bus != 0 || pa->pa_device != 0 || pa->pa_function != 0)
787 		return (0);
788 #elif defined(ALGOR_P6032)
789 	if (pa->pa_bus != 0 || pa->pa_device != 16 || pa->pa_function != 0)
790 		return (0);
791 #endif
792 
793 	if (buf != NULL)
794 		memcpy(buf, algor_ethaddr, sizeof(algor_ethaddr));
795 #if defined(ALGOR_P4032)
796 	/*
797 	 * XXX This is gross, disgusting, and otherwise vile, but
798 	 * XXX V962 rev. < B2 have broken DMA FIFOs.  Give the
799 	 * XXX on-board Ethernet a different DMA window that
800 	 * XXX has pre-fetching enabled so that Ethernet performance
801 	 * XXX doesn't completely suck.
802 	 */
803 	pa->pa_dmat = &p4032_configuration.ac_pci_pf_dmat;
804 #endif
805 	return (1);
806 }
807