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