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