1/*	$NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 1988 University of Utah.
34 * Copyright (c) 1992, 1993
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * the Systems Programming Group of the University of Utah Computer
39 * Science Department, The Mach Operating System project at
40 * Carnegie-Mellon University and Ralph Campbell.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 * 3. Neither the name of the University nor the names of its contributors
51 *    may be used to endorse or promote products derived from this software
52 *    without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 *	@(#)machdep.c   8.3 (Berkeley) 1/12/94
67 *	from: Utah Hdr: machdep.c 1.63 91/04/24
68 */
69
70#include <sys/cdefs.h>
71__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 thorpej Exp $");
72
73#include "opt_algor_p4032.h"
74#include "opt_algor_p5064.h"
75#include "opt_algor_p6032.h"
76
77#include "opt_ddb.h"
78#include "opt_kgdb.h"
79
80#include "opt_memsize.h"
81#include "opt_ethaddr.h"
82
83#include <sys/param.h>
84#include <sys/boot_flag.h>
85#include <sys/buf.h>
86#include <sys/bus.h>
87#include <sys/device.h>
88#include <sys/kernel.h>
89#include <sys/kcore.h>
90#include <sys/ksyms.h>
91#include <sys/lwp.h>
92#include <sys/mount.h>
93#include <sys/reboot.h>
94#include <sys/systm.h>
95#include <sys/termios.h>
96#include <sys/cpu.h>
97
98#include <net/if.h>
99#include <net/if_ether.h>
100
101#include <uvm/uvm_extern.h>
102
103#include <dev/cons.h>
104
105#include <mips/locore.h>
106#include <mips/pcb.h>
107
108#ifdef DDB
109#include <mips/db_machdep.h>
110#include <ddb/db_extern.h>
111#endif
112
113#include <machine/pmon.h>
114#include <algor/autoconf.h>
115
116#include <algor/pci/vtpbcvar.h>
117
118#include "ksyms.h"
119
120#include "com.h"
121#if NCOM > 0
122#include <dev/ic/comreg.h>
123#include <dev/ic/comvar.h>
124
125int	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>
138struct 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>
144struct 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>
150struct p6032_config p6032_configuration;
151#endif
152
153/* Maps for VM objects. */
154struct vm_map *phys_map = NULL;
155
156int	maxmem;			/* max memory per process */
157
158int	mem_cluster_cnt;
159phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
160
161char	algor_ethaddr[ETHER_ADDR_LEN];
162
163void	mach_init(int, char *[], char *[]);	/* XXX */
164
165int	cpuspeed = 150;		/* XXX XXX XXX */
166
167/* The ALGOR kernels only support little endian */
168CTASSERT(_BYTE_ORDER == _LITTLE_ENDIAN);
169
170void
171mach_init(int argc, char *argv[], char *envp[])
172{
173	extern char kernel_text[], edata[], end[];
174	vaddr_t kernstart, kernend;
175	vsize_t size;
176	const char *cp;
177	char *cp0;
178	size_t i;
179
180	/*
181	 * First, find the start and end of the kernel and clear
182	 * the BSS segment.  Account for a bit of space for the
183	 * bootstrap stack.
184	 */
185	led_display('b', 's', 's', ' ');
186	kernstart = (vaddr_t) mips_trunc_page(kernel_text) - 2 * NBPG;
187	kernend   = (vaddr_t) mips_round_page(end);
188	memset(edata, 0, kernend - (vaddr_t)edata);
189
190	/*
191	 * Copy the exception-dispatch code down to the exception vector.
192	 * Initialize the locore function vector.  Clear out the I- and
193	 * D-caches.
194	 *
195	 * We can no longer call into PMON after this.
196	 */
197	led_display('v', 'e', 'c', 'i');
198	mips_vector_init(NULL, false);
199
200	/*
201	 * Initialize PAGE_SIZE-dependent variables.
202	 */
203	led_display('p', 'g', 's', 'z');
204	uvm_md_init();
205
206	/*
207	 * Initialize bus space tags and bring up the console.
208	 */
209#if defined(ALGOR_P4032)
210	    {
211		struct p4032_config *acp = &p4032_configuration;
212		struct vtpbc_config *vt = &vtpbc_configuration;
213		bus_space_handle_t sh;
214
215		cpu_setmodel("Algorithmics P-4032");
216
217		vt->vt_addr = MIPS_PHYS_TO_KSEG1(P4032_V962PBC);
218		vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P4032_PCICFG);
219		vt->vt_adbase = 11;
220
221		led_display('v', '9', '6', '2');
222		vtpbc_init(&acp->ac_pc, vt);
223
224		led_display('l', 'i', 'o', ' ');
225		algor_p4032loc_bus_io_init(&acp->ac_lociot, acp);
226
227		led_display('i', 'o', ' ', ' ');
228		algor_p4032_bus_io_init(&acp->ac_iot, acp);
229
230		led_display('m', 'e', 'm', ' ');
231		algor_p4032_bus_mem_init(&acp->ac_memt, acp);
232
233		led_display('d', 'm', 'a', ' ');
234		algor_p4032_dma_init(acp);
235#if NCOM > 0
236		/*
237		 * Delay to allow firmware putchars to complete.
238		 * FIFO depth * character time.
239		 * character time = (1000000 / (defaultrate / 10))
240		 */
241		led_display('c', 'o', 'n', 's');
242		DELAY(160000000 / comcnrate);
243		if (comcnattach(&acp->ac_lociot, P4032_COM1, comcnrate,
244		    COM_FREQ, COM_TYPE_NORMAL,
245		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
246			panic("p4032: unable to initialize serial console");
247#else
248		panic("p4032: not configured to use serial console");
249#endif /* NCOM > 0 */
250
251		led_display('h', 'z', ' ', ' ');
252		bus_space_map(&acp->ac_lociot, P4032_RTC, 2, 0, &sh);
253		algor_p4032_cal_timer(&acp->ac_lociot, sh);
254		bus_space_unmap(&acp->ac_lociot, sh, 2);
255	    }
256#elif defined(ALGOR_P5064)
257	    {
258		struct p5064_config *acp = &p5064_configuration;
259		struct vtpbc_config *vt = &vtpbc_configuration;
260		bus_space_handle_t sh;
261
262		cpu_setmodel("Algorithmics P-5064");
263
264		vt->vt_addr = MIPS_PHYS_TO_KSEG1(P5064_V360EPC);
265		vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P5064_PCICFG);
266		vt->vt_adbase = 24;
267
268		led_display('v', '3', '6', '0');
269		vtpbc_init(&acp->ac_pc, vt);
270
271		led_display('i', 'o', ' ', ' ');
272		algor_p5064_bus_io_init(&acp->ac_iot, acp);
273
274		led_display('m', 'e', 'm', ' ');
275		algor_p5064_bus_mem_init(&acp->ac_memt, acp);
276
277		led_display('d', 'm', 'a', ' ');
278		algor_p5064_dma_init(acp);
279#if NCOM > 0
280		/*
281		 * Delay to allow firmware putchars to complete.
282		 * FIFO depth * character time.
283		 * character time = (1000000 / (defaultrate / 10))
284		 */
285		led_display('c', 'o', 'n', 's');
286		DELAY(160000000 / comcnrate);
287		if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
288		    COM_FREQ, COM_TYPE_NORMAL,
289		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
290			panic("p5064: unable to initialize serial console");
291#else
292		panic("p5064: not configured to use serial console");
293#endif /* NCOM > 0 */
294
295		led_display('h', 'z', ' ', ' ');
296		bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
297		algor_p5064_cal_timer(&acp->ac_iot, sh);
298		bus_space_unmap(&acp->ac_iot, sh, 2);
299	    }
300#elif defined(ALGOR_P6032)
301	    {
302		struct p6032_config *acp = &p6032_configuration;
303		struct bonito_config *bc = &acp->ac_bonito;
304		bus_space_handle_t sh;
305
306		cpu_setmodel("Algorithmics P-6032");
307
308		bc->bc_adbase = 11;
309
310		led_display('b','n','t','o');
311		bonito_pci_init(&acp->ac_pc, bc);
312
313		led_display('i','o',' ',' ');
314		algor_p6032_bus_io_init(&acp->ac_iot, acp);
315
316		led_display('m','e','m',' ');
317		algor_p6032_bus_mem_init(&acp->ac_memt, acp);
318
319		led_display('d','m','a',' ');
320		algor_p6032_dma_init(acp);
321#if NCOM > 0
322		/*
323		 * Delay to allow firmware putchars to complete.
324		 * FIFO depth * character time.
325		 * character time = (1000000 / (defaultrate / 10))
326		 */
327		led_display('c','o','n','s');
328		DELAY(160000000 / comcnrate);
329		if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
330		    COM_FREQ, COM_TYPE_NORMAL,
331		    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
332			panic("p6032: unable to initialize serial console");
333#else
334		panic("p6032: not configured to use serial console");
335#endif /* NCOM > 0 */
336
337		led_display('h','z',' ',' ');
338		bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
339		algor_p6032_cal_timer(&acp->ac_iot, sh);
340		bus_space_unmap(&acp->ac_iot, sh, 2);
341	    }
342#endif /* ALGOR_P4032 || ALGOR_P5064 || ALGOR_P6032 */
343
344	/*
345	 * The Algorithmics boards have PMON firmware; set up our
346	 * PMON state.
347	 */
348	led_display('p', 'm', 'o', 'n');
349	pmon_init(envp);
350
351	/*
352	 * Get the Ethernet address of the on-board Ethernet.
353	 */
354#if defined(ETHADDR)
355	cp = ETHADDR;
356#else
357	cp = pmon_getenv("ethaddr");
358#endif
359	if (cp != NULL) {
360		for (i = 0; i < ETHER_ADDR_LEN; i++) {
361			algor_ethaddr[i] = strtoul(cp, &cp0, 16);
362			cp = cp0 + 1;
363		}
364	}
365
366	/*
367	 * Get the boot options.
368	 */
369	led_display('b', 'o', 'p', 't');
370	boothowto = 0;
371	if (argc > 1) {
372#ifdef _LP64
373		cp = (void *)(intptr_t)((int32_t *)argv)[1];
374#else
375		cp = argv[1];
376#endif
377		for (; cp != NULL && *cp != '\0'; cp++) {
378			switch (*cp) {
379#if defined(KGDB) || defined(DDB)
380			case 'd':	/* break into kernel debugger */
381				boothowto |= RB_KDB;
382				break;
383#endif
384
385			case 'h':	/* always halt, never reboot */
386				boothowto |= RB_HALT;
387				break;
388
389			case 'n':	/* askname */
390				boothowto |= RB_ASKNAME;
391				break;
392
393			case 's':	/* single-user mode */
394				boothowto |= RB_SINGLE;
395				break;
396
397			case 'q':	/* quiet boot */
398				boothowto |= AB_QUIET;
399				break;
400
401			case 'v':	/* verbose boot */
402				boothowto |= AB_VERBOSE;
403				break;
404
405			case '-':
406				/*
407				 * Just ignore this.  It's not required,
408				 * but it's common for it to be passed
409				 * regardless.
410				 */
411				break;
412
413			default:
414				printf("Unrecognized boto flag '%c'.\n", *cp);
415				break;
416			}
417		}
418	}
419
420	/*
421	 * Determine the memory size.  Use the `memsize' PMON
422	 * variable.  If that's not available, panic.
423	 *
424	 * Note: Reserve the first page!  That's where the trap
425	 * vectors are located.
426	 */
427#if defined(MEMSIZE)
428	size = MEMSIZE;
429#else
430	if ((cp = pmon_getenv("memsize")) != NULL)
431		size = strtoul(cp, NULL, 0);
432	else {
433		printf("FATAL: `memsize' PMON variable not set.  Set it to\n");
434		printf("       the amount of memory (in MB) and try again.\n");
435		printf("       Or, build a kernel with the `MEMSIZE' "
436		    "option.\n");
437		panic("algor_init");
438	}
439#endif /* MEMSIZE */
440	/*
441	 * Deal with 2 different conventions of the contents
442	 * of the memsize variable -- if it's > 1024, assume
443	 * it's already in bytes, not megabytes.
444	 */
445	if (size < 1024) {
446		printf("Memory size: %#"PRIxVSIZE" (%"PRIxVSIZE")\n",
447		    size * 1024 * 1024, size);
448		size *= 1024 * 1024;
449	} else
450		printf("Memory size: %#"PRIxVSIZE"\n", size);
451
452	mem_clusters[mem_cluster_cnt].start = PAGE_SIZE;
453	mem_clusters[mem_cluster_cnt].size =
454	    size - mem_clusters[mem_cluster_cnt].start;
455	mem_cluster_cnt++;
456
457	/*
458	 * Load the physical memory clusters into the VM system.
459	 */
460	led_display('v', 'm', 'p', 'g');
461	for (i = 0; i < mem_cluster_cnt; i++) {
462		physmem += atop(mem_clusters[i].size);
463	}
464	if (physmem == 0)
465		panic("can't happen: system seems to have no memory!");
466	maxmem = physmem;
467
468	static const struct mips_vmfreelist isadma = {
469		.fl_start = 8*1024*1024,
470		.fl_end = 16*1024*1024,
471		.fl_freelist = VM_FREELIST_ISADMA,
472	};
473	mips_page_physload(kernstart, kernend,
474	    mem_clusters, mem_cluster_cnt, &isadma, 1);
475
476	/*
477	 * Initialize message buffer (at end of core).
478	 */
479	mips_init_msgbuf();
480
481	/*
482	 * Initialize the virtual memory system.
483	 */
484	led_display('p', 'm', 'a', 'p');
485	pmap_bootstrap();
486
487	/*
488	 * Allocate uarea page for lwp0 and set it.
489	 */
490	led_display('u', 's', 'p', 'c');
491	mips_init_lwp0_uarea();
492
493	/*
494	 * Initialize debuggers, and break into them, if appropriate.
495	 */
496	if (boothowto & RB_KDB) {
497#if defined(DDB)
498		Debugger();
499#endif
500	}
501}
502
503void
504consinit(void)
505{
506
507	/*
508	 * Everything related to console initialization is done
509	 * in mach_init().
510	 */
511	led_display('N', 'B', 'S', 'D');
512}
513
514void
515cpu_startup(void)
516{
517	/*
518	 * Virtual memory is bootstrapped -- notify the bus spaces
519	 * that memory allocation is now safe.
520	 */
521#if defined(ALGOR_P4032)
522	struct p4032_config * const acp = &p4032_configuration;
523
524	acp->ac_mallocsafe = 1;
525#elif defined(ALGOR_P5064)
526	struct p5064_config * const acp = &p5064_configuration;
527
528	acp->ac_mallocsafe = 1;
529#elif defined(ALGOR_P6032)
530	struct p6032_config * const acp = &p6032_configuration;
531
532	acp->ac_mallocsafe = 1;
533#endif
534	cpu_startup_common();
535}
536
537int	waittime = -1;
538
539void
540cpu_reboot(int howto, char *bootstr)
541{
542	int tmp;
543
544	/* Take a snapshot before clobbering any registers. */
545	savectx(curpcb);
546
547	/* If "always halt" was specified as a boot flag, obey. */
548	if (boothowto & RB_HALT)
549		howto |= RB_HALT;
550
551	boothowto = howto;
552
553	/* If system is cold, just halt. */
554	if (cold) {
555		boothowto |= RB_HALT;
556		goto haltsys;
557	}
558
559	if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
560		waittime = 0;
561		vfs_shutdown();
562	}
563
564	/* Disable interrupts. */
565	(void) splhigh();
566
567	if (boothowto & RB_DUMP)
568		dumpsys();
569
570 haltsys:
571	/* Run any shutdown hooks. */
572	doshutdownhooks();
573
574	pmf_system_shutdown(boothowto);
575
576	if (boothowto & RB_HALT) {
577		printf("\n");
578		printf("The operating system has halted.\n");
579		printf("Please press any key to return to the monitor.\n\n");
580		led_display('h','a','l','t');
581		cnpollc(1);
582		(void) cngetc();
583		cnpollc(0);
584	}
585
586	printf("Returning to the monitor...\n\n");
587	led_display('r', 'v', 'e', 'c');
588	/* Jump to the reset vector. */
589	__asm volatile("li %0, 0xbfc00000; jr %0; nop"
590		: "=r" (tmp)
591		: /* no inputs */
592		: "memory");
593	led_display('R', 'S', 'T', 'F');
594	for (;;)
595		/* spin forever */ ;
596}
597