1 /* $NetBSD: machdep.c,v 1.144 2026/09/20 10:29:12 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 37 * 38 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.144 2026/09/20 10:29:12 tsutsui Exp $"); 43 44 #include "opt_ddb.h" 45 #include "opt_modular.h" 46 #include "opt_newsconf.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/buf.h> 51 #include <sys/conf.h> 52 #include <sys/kernel.h> 53 #include <sys/device.h> 54 #include <sys/mbuf.h> 55 #include <sys/mount.h> 56 #include <sys/msgbuf.h> 57 #include <sys/proc.h> 58 #include <sys/reboot.h> 59 #include <sys/tty.h> 60 #include <sys/exec.h> 61 #include <sys/core.h> 62 #include <sys/kcore.h> 63 #include <sys/ksyms.h> 64 #include <sys/module.h> 65 #include <sys/cpu.h> 66 67 #ifdef DDB 68 #include <machine/db_machdep.h> 69 #include <ddb/db_sym.h> 70 #include <ddb/db_extern.h> 71 #endif 72 #ifdef __ELF__ 73 #include <sys/exec_elf.h> 74 #endif 75 76 #include <m68k/cacheops.h> 77 78 #include <machine/autoconf.h> 79 #include <machine/cpu.h> 80 #include <machine/reg.h> 81 #include <machine/pcb.h> 82 #include <machine/pte.h> 83 #include <machine/intr.h> 84 85 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 86 87 #include <m68k/seglist.h> 88 89 #include <dev/cons.h> 90 #include <dev/mm.h> 91 92 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 93 #include <uvm/uvm_extern.h> 94 95 #include <sys/sysctl.h> 96 97 #include <news68k/news68k/machid.h> 98 #include <news68k/news68k/isr.h> 99 100 #include "le.h" 101 #include "fbbm.h" 102 #include "kb.h" 103 #include "kb_kbc.h" 104 #include "ms.h" 105 #include "si.h" 106 #include "ksyms.h" 107 #include "romcons.h" 108 /* XXX etc. etc. */ 109 110 int maxmem; /* max memory per process */ 111 112 extern paddr_t avail_start, avail_end; 113 extern int end, *esym; 114 extern u_int lowram; 115 116 #ifdef news1700 117 static void news1700_init(void); 118 static void parityenable(void); 119 static int parityerror(void *); 120 #endif 121 #ifdef news1200 122 static void news1200_init(void); 123 #endif 124 125 /* functions called from locore.s */ 126 void machine_init(paddr_t); 127 128 int delay_divisor = delay_divisor_est(25); 129 130 /* 131 * Clamp the kernel virtual address space to keep it out of the 132 * TT ranges we use for devices. 133 */ 134 struct pmap_bootmap machine_bootmap[] = { 135 { .pmbm_vaddr = NEWS68K_IO_TT_BASE, 136 .pmbm_size = NEWS68K_IO_TT_SIZE, 137 .pmbm_flags = PMBM_F_KEEPOUT }, 138 139 { .pmbm_vaddr = NEWS68K_PROM_TT_BASE, 140 .pmbm_size = NEWS68K_PROM_TT_SIZE, 141 .pmbm_flags = PMBM_F_KEEPOUT }, 142 143 { .pmbm_vaddr = -1 }, 144 }; 145 146 /* 147 * Early initialization, before main() is called. 148 */ 149 void 150 machine_init(paddr_t nextpa) 151 { 152 /* Clear and enable the external cache, if any. */ 153 PCIA(); 154 ecacheon(); 155 156 phys_seg_list[0].ps_start = lowram; 157 phys_seg_list[0].ps_end = m68k_ptob(maxmem); 158 159 machine_init_common(nextpa); 160 161 /* Initialize system variables. */ 162 switch (systype) { 163 #ifdef news1700 164 case NEWS1700: 165 news1700_init(); 166 break; 167 #endif 168 #ifdef news1200 169 case NEWS1200: 170 news1200_init(); 171 break; 172 #endif 173 default: 174 panic("impossible system type"); 175 } 176 } 177 178 /* 179 * cpu_startup: allocate memory for variable-sized tables, 180 * initialize CPU, and do autoconfiguration. 181 */ 182 void 183 cpu_startup(void) 184 { 185 /* Initialize the interrupt handlers. */ 186 isrinit(); 187 188 #ifdef news1700 189 parityenable(); 190 #endif 191 192 cpu_startup_common(); 193 } 194 195 int news_machine_id; 196 197 void 198 machine_set_model(void) 199 { 200 /* This has already been done in newsXXXX_init() */ 201 } 202 203 void 204 machine_print_model(void (*pr)(const char *, ...) 205 __printflike(1, 2)) 206 { 207 (*pr)("SONY NET WORK STATION, Model %s, Machine ID #%d\n", 208 cpu_getmodel(), news_machine_id); 209 } 210 211 /* 212 * machine dependent system variables. 213 */ 214 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 215 { 216 217 sysctl_createv(clog, 0, NULL, NULL, 218 CTLFLAG_PERMANENT, 219 CTLTYPE_NODE, "machdep", NULL, 220 NULL, 0, NULL, 0, 221 CTL_MACHDEP, CTL_EOL); 222 223 sysctl_createv(clog, 0, NULL, NULL, 224 CTLFLAG_PERMANENT, 225 CTLTYPE_STRUCT, "console_device", NULL, 226 sysctl_consdev, 0, NULL, sizeof(dev_t), 227 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 228 } 229 230 void 231 machine_powerdown(void) 232 { 233 extern volatile uint8_t *ctrl_power; 234 235 delay(1000000); 236 *ctrl_power = 0; /* *poof* */ 237 } 238 239 /* 240 * System dependent initialization 241 */ 242 243 static volatile uint8_t *dip_switch, *int_status; 244 245 const uint8_t *idrom_addr; 246 volatile uint8_t *ctrl_ast, *ctrl_int2; 247 uint32_t sccport0a, lance_mem_phys; 248 249 #ifdef news1700 250 static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector; 251 252 struct news68k_model { 253 const int id; 254 const char *name; 255 }; 256 257 static const struct news68k_model news68k_models[] = { 258 { ICK001, "ICK001" }, /* 1 */ 259 { ICK00X, "ICK00X" }, /* 2 */ 260 { NWS799, "NWS-799" }, /* 3 */ 261 { NWS800, "NWS-800" }, /* 4 */ 262 { NWS801, "NWS-801" }, /* 5 */ 263 { NWS802, "NWS-802" }, /* 6 */ 264 { NWS711, "NWS-711" }, /* 7 */ 265 { NWS721, "NWS-721" }, /* 8 */ 266 { NWS1850, "NWS-1850" }, /* 9 */ 267 { NWS810, "NWS-810" }, /* 10 */ 268 { NWS811, "NWS-811" }, /* 11 */ 269 { NWS1830, "NWS-1830" }, /* 12 */ 270 { NWS1750, "NWS-1750" }, /* 13 */ 271 { NWS1720, "NWS-1720" }, /* 14 */ 272 { NWS1930, "NWS-1930" }, /* 15 */ 273 { NWS1960, "NWS-1960" }, /* 16 */ 274 { NWS712, "NWS-712" }, /* 17 */ 275 { NWS1860, "NWS-1860" }, /* 18 */ 276 { PWS1630, "PWS-1630" }, /* 19 */ 277 { NWS820, "NWS-820" }, /* 20 */ 278 { NWS821, "NWS-821" }, /* 21 */ 279 { NWS1760, "NWS-1760" }, /* 22 */ 280 { NWS1710, "NWS-1710" }, /* 23 */ 281 { NWS830, "NWS-830" }, /* 30 */ 282 { NWS831, "NWS-831" }, /* 31 */ 283 { NWS841, "NWS-841" }, /* 41 */ 284 { PWS1570, "PWS-1570" }, /* 52 */ 285 { PWS1590, "PWS-1590" }, /* 54 */ 286 { NWS1520, "NWS-1520" }, /* 56 */ 287 { PWS1550, "PWS-1550" }, /* 73 */ 288 { PWS1520, "PWS-1520" }, /* 74 */ 289 { PWS1560, "PWS-1560" }, /* 75 */ 290 { NWS1530, "NWS-1530" }, /* 76 */ 291 { NWS1580, "NWS-1580" }, /* 77 */ 292 { NWS1510, "NWS-1510" }, /* 78 */ 293 { NWS1410, "NWS-1410" }, /* 81 */ 294 { NWS1450, "NWS-1450" }, /* 85 */ 295 { NWS1460, "NWS-1460" }, /* 86 */ 296 { NWS891, "NWS-891" }, /* 91 */ 297 { NWS911, "NWS-911" }, /* 111 */ 298 { NWS921, "NWS-921" }, /* 121 */ 299 { 0, NULL } 300 }; 301 302 static void 303 news1700_init(void) 304 { 305 struct oidrom idrom; 306 const char *t; 307 const uint8_t *p; 308 uint8_t *q; 309 u_int i; 310 311 dip_switch = (uint8_t *)(0xe1c00100); 312 int_status = (uint8_t *)(0xe1c00200); 313 314 idrom_addr = (uint8_t *)(0xe1c00000); 315 ctrl_ast = (uint8_t *)(0xe1280000); 316 ctrl_int2 = (uint8_t *)(0xe1180000); 317 318 sccport0a = (0xe0d40002); 319 lance_mem_phys = 0xe0e00000; 320 321 p = idrom_addr; 322 q = (uint8_t *)&idrom; 323 324 for (i = 0; i < sizeof(idrom); i++, p += 2) 325 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 326 327 t = NULL; 328 for (i = 0; news68k_models[i].name != NULL; i++) { 329 if (news68k_models[i].id == idrom.id_model) { 330 t = news68k_models[i].name; 331 } 332 } 333 if (t == NULL) 334 panic("unexpected system model."); 335 336 cpu_setmodel("%s", t); 337 news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1]; 338 339 ctrl_parity = (uint8_t *)(0xe1080000); 340 ctrl_parity_clr = (uint8_t *)(0xe1a00000); 341 parity_vector = (uint8_t *)(0xe1c00200); 342 343 cpuspeed_khz = 25*1000; 344 delay_divisor = delay_divisor_est(25); 345 } 346 347 /* 348 * parity error handling (vectored NMI?) 349 */ 350 351 static void 352 parityenable(void) 353 { 354 355 if (systype != NEWS1700) 356 return; 357 358 #define PARITY_VECT 0xc0 359 #define PARITY_PRI 7 360 361 *parity_vector = PARITY_VECT; 362 363 isrlink_vectored(parityerror, NULL, PARITY_PRI, PARITY_VECT); 364 365 *ctrl_parity_clr = 1; 366 *ctrl_parity = 1; 367 368 #ifdef DEBUG 369 printf("enable parity check\n"); 370 #endif 371 } 372 373 static int innmihand; /* simple mutex */ 374 375 static int 376 parityerror(void *arg) 377 { 378 379 /* Prevent unwanted recursion. */ 380 if (innmihand) 381 return 1; 382 innmihand = 1; 383 384 #if 0 /* XXX need to implement XXX */ 385 panic("parity error"); 386 #else 387 printf("parity error detected.\n"); 388 *ctrl_parity_clr = 1; 389 #endif 390 innmihand = 0; 391 392 return 1; 393 } 394 #endif /* news1700 */ 395 396 #ifdef news1200 397 static void 398 news1200_init(void) 399 { 400 struct idrom idrom; 401 const uint8_t *p; 402 uint8_t *q; 403 int i; 404 405 dip_switch = (uint8_t *)0xe1680000; 406 int_status = (uint8_t *)0xe1200000; 407 408 idrom_addr = (uint8_t *)0xe1400000; 409 ctrl_ast = (uint8_t *)0xe1100000; 410 ctrl_int2 = (uint8_t *)0xe10c0000; 411 412 sccport0a = 0xe1780002; 413 lance_mem_phys = 0xe1a00000; 414 415 p = idrom_addr; 416 q = (uint8_t *)&idrom; 417 for (i = 0; i < sizeof(idrom); i++, p += 2) 418 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 419 420 cpu_setmodel("%s", idrom.id_model); 421 news_machine_id = idrom.id_serial; 422 423 cpuspeed_khz = 25*1000; 424 delay_divisor = delay_divisor_est(25); 425 } 426 #endif /* news1200 */ 427 428 /* 429 * interrupt handlers 430 * XXX should do better handling XXX 431 */ 432 433 void intrhand_lev3(void); 434 void intrhand_lev4(void); 435 436 void 437 intrhand_lev3(void) 438 { 439 int stat; 440 441 stat = *int_status; 442 m68k_count_intr(3); 443 #if 1 444 printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat); 445 #endif 446 } 447 448 extern int leintr(int); 449 extern int si_intr(int); 450 451 void 452 intrhand_lev4(void) 453 { 454 int stat; 455 456 #define INTST_LANCE 0x04 457 #define INTST_SCSI 0x80 458 459 stat = *int_status; 460 m68k_count_intr(4); 461 462 #if NSI > 0 463 if (stat & INTST_SCSI) { 464 si_intr(0); 465 } 466 #endif 467 #if NLE > 0 468 if (stat & INTST_LANCE) { 469 leintr(0); 470 } 471 #endif 472 #if 0 473 printf("level 4 interrupt\n"); 474 #endif 475 } 476 477 /* 478 * consinit() routines - from newsmips/cpu_cons.c 479 */ 480 481 /* 482 * Console initialization: called early on from main, 483 * before vm init or startup. Do enough configuration 484 * to choose and initialize a console. 485 * XXX need something better here. 486 */ 487 #define SCC_CONSOLE 0 488 #define SW_CONSOLE 0x07 489 #define SW_NWB512 0x04 490 #define SW_NWB225 0x01 491 #define SW_FBPOP 0x02 492 #define SW_FBPOP1 0x06 493 #define SW_FBPOP2 0x03 494 #define SW_AUTOSEL 0x07 495 496 extern struct consdev consdev_rom, consdev_zs; 497 498 #if NFBBM > 0 499 int fbbm_cnattach(void); 500 #endif 501 #if NKB_KBC > 0 502 int kb_kbc_cnattach(void); 503 #endif 504 505 int tty00_is_console = 0; 506 507 void 508 consinit(void) 509 { 510 uint8_t dipsw; 511 512 dipsw = *dip_switch; 513 514 dipsw = ~dipsw; 515 516 switch (dipsw & SW_CONSOLE) { 517 case SW_NWB225: 518 #if NFBBM > 0 && NKB_KBC > 0 519 if (systype == NEWS1700) { 520 if (fbbm_cnattach() == 0) { 521 (void)kb_kbc_cnattach(); 522 break; 523 } 524 525 /* 526 * Fixed framebuffer initialization is destructive. 527 * If takeover fails, do not assume the PROM 528 * framebuffer console remains usable. 529 */ 530 tty00_is_console = 1; 531 cn_tab = &consdev_zs; 532 (*cn_tab->cn_init)(cn_tab); 533 printf("fbbm console attach failed;" 534 " using serial console\n"); 535 break; 536 } 537 #endif 538 /* FALLTHROUGH */ 539 default: 540 #if NROMCONS > 0 541 cn_tab = &consdev_rom; 542 (*cn_tab->cn_init)(cn_tab); 543 break; 544 #endif 545 case 0: 546 tty00_is_console = 1; 547 cn_tab = &consdev_zs; 548 (*cn_tab->cn_init)(cn_tab); 549 break; 550 } 551 #if NKSYMS || defined(DDB) || defined(MODULAR) 552 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 553 (void *)&end, esym); 554 #endif 555 #ifdef DDB 556 if (boothowto & RB_KDB) 557 Debugger(); 558 #endif 559 } 560 561 int 562 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) 563 { 564 565 *handled = false; 566 if ((uint8_t *)ptr >= intiobase) 567 return EFAULT; 568 return 0; 569 } 570