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