xref: /netbsd/sys/arch/next68k/next68k/nextrom.c (revision c4a72b64)
1 /*	$NetBSD: nextrom.c,v 1.14 2002/09/11 01:46:35 mycroft Exp $	*/
2 /*
3  * Copyright (c) 1998 Darrin B. Jewell
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Darrin B. Jewell
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "opt_ddb.h"
33 #include "opt_serial.h"
34 
35 #include <sys/types.h>
36 #include <machine/cpu.h>
37 
38 #include <next68k/next68k/seglist.h>
39 #include <next68k/next68k/nextrom.h>
40 
41 #ifdef DDB
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/proc.h>
45 #define ELFSIZE 32
46 #include <sys/exec_elf.h>
47 #endif
48 
49 void    next68k_bootargs __P((unsigned char *args[]));
50 
51 int mon_getc(void);
52 int mon_putc(int c);
53 
54 extern char etext[], edata[], end[];
55 int nsym;
56 char *ssym, *esym;
57 
58 volatile struct mon_global *mg;
59 
60 
61 #define	MON(type, off) (*(type *)((u_int) (mg) + off))
62 
63 #define RELOC(v, t)	(*((t *)((u_int)&(v) + NEXT_RAMBASE)))
64 
65 #define	MONRELOC(type, off) \
66      (*(volatile type *)((u_int) RELOC(mg,volatile struct mon_global *) + off))
67 
68 
69 typedef int (*getcptr)(void);
70 typedef int (*putcptr)(int);
71 
72 /*
73  * Print a string on the rom console before the MMU is turned on
74  */
75 
76 /* #define DISABLE_ROM_PRINT 1 */
77 
78 #ifdef DISABLE_ROM_PRINT
79 #define ROM_PUTC(c)  /* nop */
80 #define ROM_PUTS(xs) /* nop */
81 #define ROM_PUTX(v)  /* nop */
82 #else
83 
84 #define ROM_PUTC(c) \
85 	(*MONRELOC(putcptr,MG_putc))(c)
86 #define ROM_PUTS(xs) \
87   do { volatile char *_s = xs + NEXT_RAMBASE; \
88      while(_s && *_s) (*MONRELOC(putcptr,MG_putc))(*_s++); \
89 	} while(0)
90 
91 /* Print a hex byte on the rom console */
92 
93 #if 1
94 static char romprint_hextable[] = "0123456789abcdef@";
95 #define ROM_PUTX(v) \
96   do { \
97     (*MONRELOC(putcptr,MG_putc)) \
98 			 ((romprint_hextable+NEXT_RAMBASE)[((v)>>4)&0xf]); \
99     (*MONRELOC(putcptr,MG_putc)) \
100 			 ((romprint_hextable+NEXT_RAMBASE)[(v)&0xf]); \
101 	} while(0);
102 #else
103 #define lookup_hex(v)  ((v)>9?('a'+(v)-0xa):('0'+(v)))
104 #define ROM_PUTX(v) \
105   do { \
106     (*MONRELOC(putcptr,MG_putc)) \
107 			 (lookup_hex(((v)>>4)&0xf)); \
108     (*MONRELOC(putcptr,MG_putc)) \
109 			 (lookup_hex((v)&0xf)); \
110 	} while(0);
111 #endif
112 #endif
113 
114 u_char rom_enetaddr[6];
115 u_char rom_boot_dev[20];
116 u_char rom_boot_arg[20];
117 u_char rom_boot_info[20];
118 u_char rom_boot_file[20];
119 u_char rom_bootfile[MG_boot_how-MG_bootfile];
120 char rom_machine_type;
121 
122 u_char *rom_return_sp;
123 u_int rom_mon_stack;
124 u_char rom_image[0x2000];
125 vm_offset_t rom_image_base;
126 u_int rom_vbr;;
127 u_int rom_intrmask;
128 u_int rom_intrstat;
129 
130 paddr_t rom_reboot_vect;
131 
132 int turbo;
133 
134 void
135 next68k_bootargs(args)
136      unsigned char *args[];
137 {
138 #ifdef DDB
139 	int i;
140 	Elf_Ehdr *ehdr;
141 	Elf_Shdr *shp;
142 	vaddr_t minsym, maxsym;
143 	char *reloc_end, *reloc_elfmag;
144 #endif
145 
146 	RELOC(rom_return_sp,u_char *) = args[0];
147 	RELOC(mg,char *) = args[1];
148 
149 	ROM_PUTS("Welcome to NetBSD/next68k\r\n");
150 
151 #ifdef DDB
152 
153 	/*
154 	 * Check the ELF headers.
155 	 */
156 
157 	reloc_end = end + NEXT_RAMBASE;
158 	reloc_elfmag = ELFMAG + NEXT_RAMBASE;
159 	ehdr = (void *)reloc_end;
160 
161 	for (i = 0; i < SELFMAG; i++) {
162 		if (ehdr->e_ident[i] != reloc_elfmag[i]) {
163 			ROM_PUTS("save_symtab: bad ELF magic\n");
164 			goto ddbdone;
165 		}
166 	}
167 	if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
168 		ROM_PUTS("save_symtab: bad ELF magic\n");
169 		goto ddbdone;
170 	}
171 
172 	/*
173 	 * Find the end of the symbols and strings.
174 	 */
175 
176 	maxsym = 0;
177 	minsym = ~maxsym;
178 	shp = (Elf_Shdr *)(reloc_end + ehdr->e_shoff);
179 	for (i = 0; i < ehdr->e_shnum; i++) {
180 		if (shp[i].sh_type != SHT_SYMTAB &&
181 		    shp[i].sh_type != SHT_STRTAB) {
182 			continue;
183 		}
184 		minsym = MIN(minsym, (vaddr_t)reloc_end + shp[i].sh_offset);
185 		maxsym = MAX(maxsym, (vaddr_t)reloc_end + shp[i].sh_offset +
186 			     shp[i].sh_size);
187 	}
188 	RELOC(nsym, int) = 1;
189 	RELOC(ssym, char *) = end;
190 	RELOC(esym, char *) = (char *)maxsym - NEXT_RAMBASE;
191 
192 	ROM_PUTS("nsym ");
193 	ROM_PUTX(RELOC(nsym, int));
194 	ROM_PUTS(" ssym ");
195 	ROM_PUTX((vaddr_t)RELOC(ssym, char *));
196 	ROM_PUTS(" esym ");
197 	ROM_PUTX((vaddr_t)RELOC(esym, char *));
198 	ROM_PUTS("\r\n");
199 
200  ddbdone:
201 #endif
202 
203 	ROM_PUTS("Constructing the segment list...\r\n");
204 
205 	ROM_PUTS("machine type = 0x");
206 	ROM_PUTX(MONRELOC(char,MG_machine_type));
207 	ROM_PUTS("\r\nboard rev = 0x");
208 	ROM_PUTX(MONRELOC(char,MG_board_rev));
209 	ROM_PUTS("\r\ndmachip = 0x");
210 	ROM_PUTX(MONRELOC(int,MG_dmachip)>>24&0xff);
211 	ROM_PUTX(MONRELOC(int,MG_dmachip)>>16&0xff);
212 	ROM_PUTX(MONRELOC(int,MG_dmachip)>>8&0xff);
213 	ROM_PUTX(MONRELOC(int,MG_dmachip)>>0&0xff);
214 	ROM_PUTS("\r\ndiskchip = 0x");
215 	ROM_PUTX(MONRELOC(int,MG_diskchip)>>24&0xff);
216 	ROM_PUTX(MONRELOC(int,MG_diskchip)>>16&0xff);
217 	ROM_PUTX(MONRELOC(int,MG_diskchip)>>8&0xff);
218 	ROM_PUTX(MONRELOC(int,MG_diskchip)>>0&0xff);
219 	ROM_PUTS("\r\n");
220 
221 
222 	/* Construct the segment list */
223 	{
224 		u_int msize16;
225 		u_int msize4;
226 		u_int msize1;
227 		int i;
228 		int j = 0;
229 		char machine;
230 
231 		if (MONRELOC(char,MG_machine_type) == NeXT_X15) {
232 			msize16 = 0x1000000;
233 			msize4  = 0x400000;
234 			msize1  = 0x100000;
235 			ROM_PUTS("Looks like a NeXT_X15\r\n");
236 		} else if (MONRELOC(char,MG_machine_type) == NeXT_WARP9C) {
237 			msize16 = 0x800000;
238 			msize4  = 0x200000;
239 			msize1  = 0x80000;				/* ? */
240 			ROM_PUTS("Looks like a NeXT_WARP9C\r\n");
241 		} else if (MONRELOC(char,MG_machine_type) == NeXT_WARP9) {
242 			msize16 = 0x1000000;
243 			msize4  = 0x400000;
244 			msize1  = 0x100000;
245 			ROM_PUTS("Looks like a NeXT_WARP9\r\n");
246 		} else if (MONRELOC(char,MG_machine_type) == NeXT_TURBO_COLOR) {
247 			msize16 = 0x2000000;
248 			msize4  = 0x800000;
249 			msize1  = 0x200000;
250 			ROM_PUTS("Looks like a NeXT_TURBO_COLOR\r\n");
251 		} else if (MONRELOC(char,MG_machine_type) == NeXT_TURBO_MONO) {
252 			msize16 = 0x2000000;
253 			msize4  = 0x800000;
254 			msize1  = 0x200000;
255 			ROM_PUTS("Looks like a NeXT_TURBO_MONO\r\n");
256 		} else {
257 			msize16 = 0x100000;
258 			msize4  = 0x100000;
259 			msize1  = 0x100000;
260 			ROM_PUTS("Unrecognized machine_type\r\n");
261 		}
262 
263 		machine = MONRELOC(char, MG_machine_type);
264 		RELOC(rom_machine_type, char) = machine;
265 		if (machine == NeXT_TURBO_MONO || machine == NeXT_TURBO_COLOR)
266 			RELOC(turbo, int) = 1;
267 		else
268 			RELOC(turbo, int) = 0;
269 
270 		for (i=0;i<N_SIMM;i++) {
271 
272 			ROM_PUTS("Memory bank 0x");
273 			ROM_PUTX(i);
274 			ROM_PUTS(" has value 0x");
275 			ROM_PUTX(MONRELOC(char,MG_simm+i))
276 				ROM_PUTS("\r\n");
277 
278 			if ((MONRELOC(char,MG_simm+i) & SIMM_SIZE) != SIMM_SIZE_EMPTY) {
279 				RELOC(phys_seg_list[j].ps_start, vm_offset_t)
280 					= NEXT_RAMBASE+(i*msize16);
281 			}
282 			if ((MONRELOC(char,MG_simm+i) & SIMM_SIZE) == SIMM_SIZE_16MB) {
283 				RELOC(phys_seg_list[j].ps_end, vm_offset_t) =
284 					RELOC(phys_seg_list[j].ps_start, vm_offset_t) +
285 					msize16;
286 				j++;
287 			}
288 			if ((MONRELOC(char,MG_simm+i) & SIMM_SIZE) == SIMM_SIZE_4MB) {
289 				RELOC(phys_seg_list[j].ps_end, vm_offset_t) =
290 					RELOC(phys_seg_list[j].ps_start, vm_offset_t) +
291 					msize4;
292 				j++;
293 			}
294 			if ((MONRELOC(char,MG_simm+i) & SIMM_SIZE) == SIMM_SIZE_1MB) {
295 				RELOC(phys_seg_list[j].ps_end, vm_offset_t) =
296 					RELOC(phys_seg_list[j].ps_start, vm_offset_t) +
297 					msize1;
298 				j++;
299 			}
300 		}
301 
302 		/* The NeXT ROM or something appears to reserve the very
303 		 * top of memory
304 		 */
305 		RELOC(phys_seg_list[j-1].ps_end, vm_offset_t) -= 0x2000;
306 		RELOC(rom_image_base, vm_offset_t) = RELOC(phys_seg_list[j-1].ps_end, vm_offset_t);
307 
308 		/* pmap is unhappy if it is not null terminated */
309 		for(;j<MAX_PHYS_SEGS;j++) {
310 			RELOC(phys_seg_list[j].ps_start, vm_offset_t) = 0;
311 			RELOC(phys_seg_list[j].ps_end, vm_offset_t) = 0;
312 		}
313 	}
314 
315 	{
316 		int i;
317 		ROM_PUTS("Memory segments found:\r\n");
318 		for (i=0;RELOC(phys_seg_list[i].ps_start, vm_offset_t);i++) {
319 			ROM_PUTS("\t0x");
320 			ROM_PUTX((RELOC(phys_seg_list[i].ps_start, vm_offset_t)>>24)&0xff);
321 			ROM_PUTX((RELOC(phys_seg_list[i].ps_start, vm_offset_t)>>16)&0xff);
322 			ROM_PUTX((RELOC(phys_seg_list[i].ps_start, vm_offset_t)>>8)&0xff);
323 			ROM_PUTX((RELOC(phys_seg_list[i].ps_start, vm_offset_t)>>0)&0xff);
324 			ROM_PUTS(" - 0x");
325 			ROM_PUTX((RELOC(phys_seg_list[i].ps_end, vm_offset_t)>>24)&0xff);
326 			ROM_PUTX((RELOC(phys_seg_list[i].ps_end, vm_offset_t)>>16)&0xff);
327 			ROM_PUTX((RELOC(phys_seg_list[i].ps_end, vm_offset_t)>>8)&0xff);
328 			ROM_PUTX((RELOC(phys_seg_list[i].ps_end, vm_offset_t)>>0)&0xff);
329 			ROM_PUTS("\r\n");
330 		}
331 	}
332 
333 	/* Read the ethernet address from rom, this should be done later
334 	 * in device driver somehow.
335 	 */
336 	{
337 		int i;
338 		ROM_PUTS("Ethernet address: ");
339 		for(i=0;i<6;i++) {
340 			RELOC(rom_enetaddr[i], u_char) = MONRELOC(u_char *, MG_clientetheraddr)[i];
341 			ROM_PUTX(RELOC(rom_enetaddr[i],u_char));
342 			if (i < 5) ROM_PUTS(":");
343 		}
344 		ROM_PUTS("\r\n");
345 	}
346 
347 	/* Read the boot args
348 	 */
349 	{
350 		int i;
351 		for(i=0;i<sizeof(rom_bootfile);i++) {
352 			RELOC(rom_bootfile[i], u_char) = MONRELOC(u_char, MG_bootfile+i);
353 		}
354 
355 		ROM_PUTS("rom bootdev: ");
356 		for(i=0;i<sizeof(rom_boot_dev);i++) {
357 			RELOC(rom_boot_dev[i], u_char) = MONRELOC(u_char *, MG_boot_dev)[i];
358 			ROM_PUTC(RELOC(rom_boot_dev[i], u_char));
359 			if (MONRELOC(u_char *, MG_boot_dev)[i] == '\0') break;
360 		}
361 		RELOC(rom_boot_dev[sizeof(rom_boot_dev)-1], u_char) = 0;
362 
363 		ROM_PUTS("\r\nrom bootarg: ");
364 		for(i=0;i<sizeof(rom_boot_arg);i++) {
365 			RELOC(rom_boot_arg[i], u_char) = MONRELOC(u_char *, MG_boot_arg)[i];
366 			ROM_PUTC(RELOC(rom_boot_arg[i], u_char));
367 			if (MONRELOC(u_char *, MG_boot_arg)[i] == '\0') break;
368 		}
369 		RELOC(rom_boot_arg[sizeof(rom_boot_arg)-1], u_char) = 0;
370 
371 		ROM_PUTS("\r\nrom bootinfo: ");
372 		for(i=0;i<sizeof(rom_boot_info);i++) {
373 			RELOC(rom_boot_info[i], u_char) = MONRELOC(u_char *, MG_boot_info)[i];
374 			ROM_PUTC(RELOC(rom_boot_info[i], u_char));
375 			if (MONRELOC(u_char *, MG_boot_info)[i] == '\0') break;
376 		}
377 		RELOC(rom_boot_info[sizeof(rom_boot_info)-1], u_char) = 0;
378 
379 		ROM_PUTS("\r\nrom bootfile: ");
380 		for(i=0;i<sizeof(rom_boot_file);i++) {
381 			RELOC(rom_boot_file[i], u_char) = MONRELOC(u_char *, MG_boot_file)[i];
382 			ROM_PUTC(RELOC(rom_boot_file[i], u_char));
383 			if (MONRELOC(u_char *, MG_boot_file)[i] == '\0') break;
384 		}
385 		RELOC(rom_boot_file[sizeof(rom_boot_file)-1], u_char) = 0;
386 		ROM_PUTS("\r\n");
387 
388 		RELOC(rom_mon_stack, u_int) = MONRELOC(u_int, MG_mon_stack);
389 		RELOC(rom_vbr, u_int) = MONRELOC(u_int, MG_vbr);
390 		RELOC(rom_reboot_vect, paddr_t) = MONRELOC(paddr_t *, MG_vbr)[45]; /* trap #13 */
391 
392 		for(i=0;i<sizeof(rom_image);i++) {
393 			RELOC(rom_image[i], u_char) = *(u_char *)(RELOC(rom_image_base, vm_offset_t) + i);
394 		}
395 	}
396 
397 	RELOC(rom_intrmask, u_int) = MONRELOC(u_int, MG_intrmask);
398 	RELOC(rom_intrstat, u_int) = MONRELOC(u_int, MG_intrstat);
399 	ROM_PUTS("intrmask: ");
400 	ROM_PUTX((RELOC(rom_intrmask, u_int)>>24)&0xff);
401 	ROM_PUTX((RELOC(rom_intrmask, u_int)>>16)&0xff);
402 	ROM_PUTX((RELOC(rom_intrmask, u_int)>>8)&0xff);
403 	ROM_PUTX((RELOC(rom_intrmask, u_int)>>0)&0xff);
404 	ROM_PUTS("\r\nintrstat: ");
405 	ROM_PUTX((RELOC(rom_intrstat, u_int)>>24)&0xff);
406 	ROM_PUTX((RELOC(rom_intrstat, u_int)>>16)&0xff);
407 	ROM_PUTX((RELOC(rom_intrstat, u_int)>>8)&0xff);
408 	ROM_PUTX((RELOC(rom_intrstat, u_int)>>0)&0xff);
409 	ROM_PUTS("\r\n");
410  /*	RELOC(rom_intrmask, u_int) = 0x02007800; */
411  /*	RELOC(rom_intrstat, u_int) = 0x02007000; */
412 
413 #ifdef SERCONSOLE
414 	ROM_PUTS("Check serial port A for console.\r\n");
415 #endif
416 }
417