1 /* $NetBSD: machdep.c,v 1.12 2021/12/08 20:50:02 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tim Rightnour 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.12 2021/12/08 20:50:02 andvar Exp $"); 34 35 #include "opt_compat_netbsd.h" 36 #include "opt_ddb.h" 37 #include "opt_modular.h" 38 39 #include <sys/param.h> 40 #include <sys/buf.h> 41 #include <sys/bus.h> 42 #include <sys/conf.h> 43 #include <sys/device.h> 44 #include <sys/exec.h> 45 #include <sys/extent.h> 46 #include <sys/intr.h> 47 #include <sys/kernel.h> 48 #include <sys/ksyms.h> 49 #include <sys/malloc.h> 50 #include <sys/mbuf.h> 51 #include <sys/mount.h> 52 #include <sys/msgbuf.h> 53 #include <sys/proc.h> 54 #include <sys/reboot.h> 55 #include <sys/syscallargs.h> 56 #include <sys/sysctl.h> 57 #include <sys/syslog.h> 58 #include <sys/systm.h> 59 60 #include <uvm/uvm_extern.h> 61 62 #include <machine/autoconf.h> 63 #include <machine/bootinfo.h> 64 #include <machine/powerpc.h> 65 #include <machine/iplcb.h> 66 67 #include <powerpc/pmap.h> 68 #include <powerpc/trap.h> 69 70 #include <powerpc/oea/bat.h> 71 #include <powerpc/pio.h> 72 #include <powerpc/pic/picvar.h> 73 74 #include <dev/cons.h> 75 76 #include "com.h" 77 #if (NCOM > 0) 78 #include <sys/termios.h> 79 #include <dev/ic/comreg.h> 80 #include <dev/ic/comvar.h> 81 void comsoft(void); 82 #endif 83 84 #ifdef DDB 85 #include <powerpc/db_machdep.h> 86 #include <ddb/db_extern.h> 87 #endif 88 89 #include "ksyms.h" 90 91 void initppc(u_long, u_long, u_int, void *); 92 void dumpsys(void); 93 void strayintr(int); 94 void rs6000_bus_space_init(void); 95 void setled(uint32_t); 96 void say_hi(void); 97 static void init_intr(void); 98 99 char bootinfo[BOOTINFO_MAXSIZE]; 100 char bootpath[256]; 101 struct ipl_directory *ipldir; 102 struct ipl_cb *iplcb; 103 struct ipl_info *iplinfo; 104 int led_avail; 105 struct sys_info *sysinfo; 106 struct buc_info *bucinfo[MAX_BUCS]; 107 int nrofbucs; 108 109 struct pic_ops *pic_iocc; 110 111 #define OFMEMREGIONS 32 112 struct mem_region physmemr[OFMEMREGIONS], availmemr[OFMEMREGIONS]; 113 114 paddr_t avail_end; /* XXX temporary */ 115 extern register_t iosrtable[16]; 116 117 #if NKSYMS || defined(DDB) || defined(MODULAR) 118 extern void *endsym, *startsym; 119 #endif 120 121 #ifndef CONCOMADDR 122 #define CONCOMADDR 0x30 123 #endif 124 125 #ifndef CONSPEED 126 #define CONSPEED 9600 127 #endif 128 129 #ifndef CONMODE 130 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 131 #endif 132 133 int comcnspeed = CONSPEED; 134 int comcnmode = CONMODE; 135 struct consdev kcomcons; 136 static void kcomcnputc(dev_t, int); 137 138 extern struct pic_ops *setup_iocc(void); 139 140 141 void 142 say_hi(void) 143 { 144 printf("HELLO?!\n"); 145 setled(0x55500000); 146 #ifdef DDB 147 Debugger(); 148 #endif 149 #if 0 150 li %r28,0x00000041 /* PUT A to R28*/ 151 li %r29,0x30 /* put serial addr to r29*/ 152 addis %r29,%r29,0xc000 /* r29 now holds serial addr*/ 153 stb %r28,0(%r29) /* slam it to serial port*/ 154 loopforever: 155 bla loopforever 156 #endif 157 } 158 /* 159 * Set LED's. Yes I know this is ugly. Yes I will rewrite it in pure asm. 160 */ 161 void 162 setled(uint32_t val) 163 { 164 #if 0 165 register_t savemsr, msr, savesr15; 166 167 __asm volatile ("mfmsr %0" : "=r"(savemsr)); 168 msr = savemsr & ~PSL_DR; 169 __asm volatile ("mtmsr %0" : : "r"(msr)); 170 171 __asm volatile ("mfsr %0,15;isync" : "=r"(savesr15)); 172 __asm volatile ("mtsr 15,%0" : : "r"(0x82040080)); 173 __asm volatile ("mtmsr %0" : : "r"(msr|PSL_DR)); 174 __asm volatile ("isync"); 175 *(uint32_t *)0xF0A00300 = val; 176 __asm volatile ("mtmsr %0" : : "r"(savemsr)); 177 __asm volatile ("mtsr 15,%0;isync" : : "r"(savesr15)); 178 #endif 179 if (led_avail) 180 *(uint32_t *)0xFF600300 = val; 181 } 182 183 #if 0 184 int 185 power_cputype(void) 186 { 187 uint32_t model; 188 189 model = iplinfo->model; 190 if (model & 0x08000000) { 191 /* ppc */ 192 return 0; 193 } else if (model & 0x02000000) 194 return POWER_RSC; 195 else if (model & 0x04000000) 196 return POWER_2; 197 else 198 return POWER_1; 199 } 200 #endif 201 202 203 void 204 initppc(u_long startkernel, u_long endkernel, u_int args, void *btinfo) 205 { 206 u_long ekern; 207 struct ipl_cb *r_iplcb; 208 struct ipl_directory *r_ipldir; 209 struct buc_info *bi; 210 int i; 211 register_t savemsr, msr; 212 213 /* indicate we have control */ 214 //setled(0x40000000); 215 *(uint8_t *)0xe0000030 = '1'; 216 217 /* copy bootinfo */ 218 memcpy(bootinfo, btinfo, sizeof(bootinfo)); 219 *(uint8_t *)0xe0000030 = '2'; 220 221 /* copy iplcb data */ 222 { 223 struct btinfo_iplcb *iplcbinfo; 224 225 iplcbinfo = 226 (struct btinfo_iplcb *)lookup_bootinfo(BTINFO_IPLCB); 227 if (!iplcbinfo) 228 panic("no iplcb information found in bootinfo"); 229 230 /* round_page endkernel, copy down to there, adjust */ 231 ekern = round_page(endkernel); 232 233 r_iplcb = (struct ipl_cb *)iplcbinfo->addr; 234 r_ipldir = (struct ipl_directory *)&r_iplcb->dir; 235 memcpy((void *)ekern, r_iplcb, r_ipldir->cb_bitmap_size); 236 iplcb = (struct ipl_cb *)ekern; 237 ipldir = (struct ipl_directory *)&iplcb->dir; 238 iplinfo = (struct ipl_info *)((char *)iplcb + 239 ipldir->iplinfo_off); 240 sysinfo = (struct sys_info *)((char *)iplcb + 241 ipldir->sysinfo_offset); 242 243 ekern += r_ipldir->cb_bitmap_size; 244 endkernel = ekern; 245 246 } 247 248 /* IPLCB copydown successful */ 249 setled(0x40100000); 250 251 /* Set memory region */ 252 { 253 u_long memsize = iplinfo->ram_size; 254 255 /* 256 * Some machines incorrectly report memory size in 257 * MB. Stupid stupid IBM breaking their own spec. 258 * on conformant machines, it is: 259 * The highest addressable real memory address byte+1 260 */ 261 if (memsize < 4069) 262 memsize = memsize * 1024 * 1024; 263 else 264 memsize -= 1; 265 physmemr[0].start = 0; 266 physmemr[0].size = memsize & ~PGOFSET; 267 availmemr[0].start = round_page(endkernel); 268 availmemr[0].size = memsize - availmemr[0].start; 269 } 270 avail_end = physmemr[0].start + physmemr[0].size; /* XXX temporary */ 271 *(uint8_t *)0xe0000030 = '3'; 272 273 #ifdef NOTYET 274 /* hrmm.. there is no timebase crap on POWER */ 275 /* 276 * Set CPU clock 277 */ 278 { 279 struct btinfo_clock *clockinfo; 280 extern u_long ticks_per_sec, ns_per_tick; 281 282 clockinfo = 283 (struct btinfo_clock *)lookup_bootinfo(BTINFO_CLOCK); 284 if (!clockinfo) 285 panic("not found clock information in bootinfo"); 286 287 ticks_per_sec = clockinfo->ticks_per_sec; 288 ns_per_tick = 1000000000 / ticks_per_sec; 289 } 290 #endif 291 /* boothowto */ 292 boothowto = args; 293 294 /* 295 * Now setup fixed bat registers 296 * 1) POWER has no bat registers. 297 * 2) NVRAM, IPL ROM, and other fun bits all live at 0xFF000000 on the 298 * 60x RS6000's, however if you try to map any less than 256MB 299 * on a 601 it wedges. 300 */ 301 #if !defined(POWER) 302 setled(0x40200000); 303 oea_batinit( 304 0xF0000000, BAT_BL_256M, 305 /* 306 RS6000_BUS_SPACE_MEM, BAT_BL_256M, 307 RS6000_BUS_SPACE_IO, BAT_BL_256M, 308 0xbf800000, BAT_BL_8M, 309 */ 310 0); 311 led_avail = 1; 312 #endif 313 setled(0x40200000); 314 315 /* set the IO segreg for the first IOCC */ 316 #ifdef POWER 317 iosrtable[0xc] = 0x820C00E0; 318 #else 319 iosrtable[0xc] = 0x82000080; 320 #endif 321 __asm volatile ("mfmsr %0" : "=r"(savemsr)); 322 msr = savemsr & ~PSL_DR; 323 __asm volatile ("mtmsr %0" : : "r"(msr)); 324 __asm volatile ("mtsr 0xc,%0" : : "r"(iosrtable[0xc])); 325 __asm volatile ("mtmsr %0" : : "r"(msr|PSL_DR)); 326 __asm volatile ("isync"); 327 __asm volatile ("mtmsr %0;isync" : : "r"(savemsr)); 328 329 cn_tab = &kcomcons; 330 printf("\nNetBSD/rs6000 booting ...\n"); 331 setled(0x40300000); 332 333 /* Install vectors and interrupt handler. */ 334 oea_init(NULL); 335 setled(0x40400000); 336 337 /* Initialize pmap module. */ 338 uvm_md_init(); 339 pmap_bootstrap(startkernel, endkernel); 340 setled(0x40500000); 341 342 /* populate the bucinfo stuff now that we can malloc */ 343 bi = (struct buc_info *)((char *)iplcb + ipldir->bucinfo_off); 344 nrofbucs = bi->nrof_structs; 345 /*printf("nrof=%d\n", nrofbucs);*/ 346 if (nrofbucs > MAX_BUCS) 347 aprint_error("WARNING: increase MAX_BUCS to at least %d\n", 348 nrofbucs); 349 for (i=0; i < nrofbucs && i < MAX_BUCS; i++) { 350 #ifdef DEBUG 351 printf("bi addr= %p\n", &bi); 352 printf("i=%d ssize=%x\n", i, bi->struct_size); 353 #endif 354 bucinfo[i] = bi; 355 bi = (struct buc_info *)((char *)iplcb + ipldir->bucinfo_off + 356 bi->struct_size); 357 } 358 #ifdef DEBUG 359 printf("found %d bucs\n", nrofbucs); 360 for (i=0; i < nrofbucs; i++) { 361 printf("BUC type: %d\n", bucinfo[i]->dev_type); 362 printf("BUC cfg incr: %x\n", bucinfo[i]->cfg_addr_incr); 363 printf("BUC devid reg: %x\n", bucinfo[i]->device_id_reg); 364 printf("BUC iocc?= %d\n", bucinfo[i]->IOCC_flag); 365 printf("BUC location= %x%x%x%x\n", bucinfo[i]->location[0], 366 bucinfo[i]->location[1], bucinfo[i]->location[2], 367 bucinfo[i]->location[3]); 368 } 369 printf("sysinfo scr_addr %p -> %x\n", sysinfo->scr_addr, 370 *sysinfo->scr_addr); 371 #endif 372 373 /* Initialize bus_space. */ 374 rs6000_bus_space_init(); 375 setled(0x40600000); 376 377 /* Initialize the console */ 378 consinit(); 379 setled(0x41000000); 380 381 #if NKSYMS || defined(DDB) || defined(MODULAR) 382 ksyms_addsyms_elf((int)((u_long)endsym - (u_long)startsym), startsym, endsym); 383 #endif 384 385 #ifdef DDB 386 if (boothowto & RB_KDB) 387 Debugger(); 388 #endif 389 } 390 391 void 392 mem_regions(struct mem_region **mem, struct mem_region **avail) 393 { 394 395 *mem = physmemr; 396 *avail = availmemr; 397 } 398 399 static void 400 init_intr(void) 401 { 402 pic_init(); 403 pic_iocc = setup_iocc(); 404 oea_install_extint(pic_ext_intr); 405 } 406 407 /* 408 * Machine dependent startup code. 409 */ 410 void 411 cpu_startup(void) 412 { 413 /* 420 indicates we are entering cpu_startup() */ 414 setled(0x42000000); 415 /* Do common startup. */ 416 oea_startup("rs6000"); 417 418 /* 419 * Inititalize the IOCC interrupt stuff 420 */ 421 init_intr(); 422 423 /* 424 * Now allow hardware interrupts. 425 */ 426 { 427 int msr; 428 429 splraise(-1); 430 __asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 431 : "=r"(msr) : "K"(PSL_EE)); 432 setled(0x42200000); 433 } 434 /* 435 * Now safe for bus space allocation to use malloc. 436 */ 437 bus_space_mallocok(); 438 } 439 440 /* 441 * lookup_bootinfo: 442 * Look up information in bootinfo of boot loader. 443 */ 444 void * 445 lookup_bootinfo(int type) 446 { 447 struct btinfo_common *bt; 448 struct btinfo_common *help = (struct btinfo_common *)bootinfo; 449 450 do { 451 bt = help; 452 if (bt->type == type) 453 return (help); 454 help = (struct btinfo_common *)((char*)help + bt->next); 455 } while (bt->next && 456 (size_t)help < (size_t)bootinfo + sizeof (bootinfo)); 457 458 return (NULL); 459 } 460 461 /* 462 * Reboot an RS6K 463 */ 464 static void 465 reset_rs6000(void) 466 { 467 mtmsr(mfmsr() | PSL_IP); 468 469 /* writing anything to the power/reset reg on an rs6k will cause 470 * a soft reboot. Supposedly. 471 */ 472 if (sysinfo->prcr_addr) 473 outb(sysinfo->prcr_addr, 0x1); 474 } 475 476 /* 477 * Halt or reboot the machine after syncing/dumping according to howto. 478 */ 479 void 480 cpu_reboot(int howto, char *what) 481 { 482 static int syncing; 483 484 if (cold) { 485 howto |= RB_HALT; 486 goto halt_sys; 487 } 488 489 boothowto = howto; 490 if ((howto & RB_NOSYNC) == 0 && syncing == 0) { 491 syncing = 1; 492 vfs_shutdown(); /* sync */ 493 //resettodr(); /* set wall clock */ 494 } 495 496 /* Disable intr */ 497 splhigh(); 498 499 /* Do dump if requested */ 500 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 501 oea_dumpsys(); 502 503 halt_sys: 504 doshutdownhooks(); 505 506 pmf_system_shutdown(boothowto); 507 508 if (howto & RB_HALT) { 509 printf("\n"); 510 printf("The operating system has halted.\n"); 511 printf("Please press any key to reboot.\n\n"); 512 cnpollc(1); /* for proper keyboard command handling */ 513 cngetc(); 514 cnpollc(0); 515 } 516 517 printf("rebooting...\n\n"); 518 519 reset_rs6000(); 520 521 for (;;) 522 continue; 523 /* NOTREACHED */ 524 } 525 526 /* The iocc0 mapping is set by init_ppc to 0xC via an iosegreg */ 527 struct powerpc_bus_space rs6000_iocc0_io_space_tag = { 528 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 529 .pbs_offset = 0xC0000000, 530 .pbs_base = 0x00000000, 531 .pbs_limit = 0x10000000, 532 }; 533 534 static char ex_storage[2][EXTENT_FIXED_STORAGE_SIZE(8)] 535 __attribute__((aligned(8))); 536 537 void 538 rs6000_bus_space_init(void) 539 { 540 int error; 541 542 error = bus_space_init(&rs6000_iocc0_io_space_tag, "ioport", 543 ex_storage[0], sizeof(ex_storage[0])); 544 if (error) 545 panic("rs6000_bus_space_init: can't init io tag"); 546 547 #if 0 548 error = extent_alloc_region(rs6000_iocc0_io_space_tag.pbs_extent, 549 0x10000, 0x7F0000, EX_NOWAIT); 550 if (error) 551 panic("rs6000_bus_space_init: can't block out reserved I/O" 552 " space 0x10000-0x7fffff: error=%d", error); 553 error = bus_space_init(&prep_mem_space_tag, "iomem", 554 ex_storage[1], sizeof(ex_storage[1])); 555 if (error) 556 panic("prep_bus_space_init: can't init mem tag"); 557 558 rs6000_iocc0_io_space_tag.pbs_extent = prep_io_space_tag.pbs_extent; 559 error = bus_space_init(&prep_isa_io_space_tag, "isa-ioport", NULL, 0); 560 if (error) 561 panic("prep_bus_space_init: can't init isa io tag"); 562 563 prep_isa_mem_space_tag.pbs_extent = prep_mem_space_tag.pbs_extent; 564 error = bus_space_init(&prep_isa_mem_space_tag, "isa-iomem", NULL, 0); 565 if (error) 566 panic("prep_bus_space_init: can't init isa mem tag"); 567 #endif 568 } 569 570 static bus_space_handle_t kcom_base = (bus_space_handle_t) (0xc0000000 + CONCOMADDR); 571 extern void bsw1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int8_t v); 572 extern int bsr1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o); 573 #define KCOM_GETBYTE(r) bsr1(0, kcom_base, (r)) 574 #define KCOM_PUTBYTE(r,v) bsw1(0, kcom_base, (r), (v)) 575 576 static int 577 kcomcngetc(dev_t dev) 578 { 579 int stat, c; 580 register_t msr; 581 582 msr = mfmsr(); 583 mtmsr(msr|PSL_DR); 584 __asm volatile ("isync"); 585 586 /* block until a character becomes available */ 587 while (!ISSET(stat = KCOM_GETBYTE(com_lsr), LSR_RXRDY)) 588 ; 589 590 c = KCOM_GETBYTE(com_data); 591 stat = KCOM_GETBYTE(com_iir); 592 mtmsr(msr); 593 __asm volatile ("isync"); 594 return c; 595 } 596 597 /* 598 * Console kernel output character routine. 599 */ 600 static void 601 kcomcnputc(dev_t dev, int c) 602 { 603 int timo; 604 register_t msr; 605 606 msr = mfmsr(); 607 mtmsr(msr|PSL_DR); 608 __asm volatile ("isync"); 609 /* wait for any pending transmission to finish */ 610 timo = 150000; 611 while (!ISSET(KCOM_GETBYTE(com_lsr), LSR_TXRDY) && --timo) 612 continue; 613 614 KCOM_PUTBYTE(com_data, c); 615 616 /* wait for this transmission to complete */ 617 timo = 1500000; 618 while (!ISSET(KCOM_GETBYTE(com_lsr), LSR_TXRDY) && --timo) 619 continue; 620 mtmsr(msr); 621 __asm volatile ("isync"); 622 } 623 624 static void 625 kcomcnpollc(dev_t dev, int on) 626 { 627 } 628 629 struct consdev kcomcons = { 630 NULL, NULL, kcomcngetc, kcomcnputc, kcomcnpollc, NULL, 631 NULL, NULL, NODEV, CN_NORMAL 632 }; 633