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