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