xref: /netbsd-src/sys/arch/algor/algor/machdep.c (revision f36002f244a49908fef9cba8789032bdbf48d572)
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 
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 /* Maps for VM objects. */
154 struct vm_map *phys_map = NULL;
155 
156 int	maxmem;			/* max memory per process */
157 
158 int	mem_cluster_cnt;
159 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
160 
161 char	algor_ethaddr[ETHER_ADDR_LEN];
162 
163 void	mach_init(int, char *[], char *[]);	/* XXX */
164 
165 int	cpuspeed = 150;		/* XXX XXX XXX */
166 
167 /* The ALGOR kernels only support little endian */
168 CTASSERT(_BYTE_ORDER == _LITTLE_ENDIAN);
169 
170 void
mach_init(int argc,char * argv[],char * envp[])171 mach_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 
503 void
consinit(void)504 consinit(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 
514 void
cpu_startup(void)515 cpu_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 
537 int	waittime = -1;
538 
539 void
cpu_reboot(int howto,char * bootstr)540 cpu_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