1 /* $NetBSD: machdep.c,v 1.5 2011/01/14 02:06:25 rmind Exp $ */ 2 3 /* 4 * Copyright 2001, 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe and Simon Burge for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Copyright (c) 1992, 1993 40 * The Regents of the University of California. All rights reserved. 41 * 42 * This code is derived from software contributed to Berkeley by 43 * the Systems Programming Group of the University of Utah Computer 44 * Science Department, The Mach Operating System project at 45 * Carnegie-Mellon University and Ralph Campbell. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 72 * from: Utah Hdr: machdep.c 1.63 91/04/24 73 */ 74 /* 75 * Copyright (c) 1988 University of Utah. 76 * 77 * This code is derived from software contributed to Berkeley by 78 * the Systems Programming Group of the University of Utah Computer 79 * Science Department, The Mach Operating System project at 80 * Carnegie-Mellon University and Ralph Campbell. 81 * 82 * Redistribution and use in source and binary forms, with or without 83 * modification, are permitted provided that the following conditions 84 * are met: 85 * 1. Redistributions of source code must retain the above copyright 86 * notice, this list of conditions and the following disclaimer. 87 * 2. Redistributions in binary form must reproduce the above copyright 88 * notice, this list of conditions and the following disclaimer in the 89 * documentation and/or other materials provided with the distribution. 90 * 3. All advertising materials mentioning features or use of this software 91 * must display the following acknowledgement: 92 * This product includes software developed by the University of 93 * California, Berkeley and its contributors. 94 * 4. Neither the name of the University nor the names of its contributors 95 * may be used to endorse or promote products derived from this software 96 * without specific prior written permission. 97 * 98 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 99 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 100 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 101 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 102 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 103 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 104 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 105 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 106 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 107 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 108 * SUCH DAMAGE. 109 * 110 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 111 * from: Utah Hdr: machdep.c 1.63 91/04/24 112 */ 113 114 #include <sys/cdefs.h> 115 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.5 2011/01/14 02:06:25 rmind Exp $"); 116 117 #include "opt_ddb.h" 118 #include "opt_com.h" 119 #include "opt_execfmt.h" 120 #include "opt_memsize.h" 121 122 #include <sys/param.h> 123 #include <sys/systm.h> 124 #include <sys/kernel.h> 125 #include <sys/buf.h> 126 #include <sys/reboot.h> 127 #include <sys/mount.h> 128 #include <sys/kcore.h> 129 #include <sys/boot_flag.h> 130 #include <sys/termios.h> 131 #include <sys/ksyms.h> 132 #include <sys/bus.h> 133 #include <sys/device.h> 134 #include <sys/extent.h> 135 #include <sys/malloc.h> 136 137 #include <uvm/uvm_extern.h> 138 139 #include <dev/cons.h> 140 141 #include "ksyms.h" 142 143 #if NKSYMS || defined(DDB) || defined(LKM) 144 #include <machine/db_machdep.h> 145 #include <ddb/db_extern.h> 146 #endif 147 148 #include <machine/cpu.h> 149 #include <machine/psl.h> 150 151 #include "com.h" 152 #if NCOM == 0 153 #error no serial console 154 #endif 155 156 #include <dev/ic/comreg.h> 157 #include <dev/ic/comvar.h> 158 159 #include <mips/rmi/rmixl_comvar.h> 160 #include <mips/rmi/rmixlvar.h> 161 #include <mips/rmi/rmixl_firmware.h> 162 #include <mips/rmi/rmixlreg.h> 163 164 #define MACHDEP_DEBUG 1 165 #ifdef MACHDEP_DEBUG 166 int machdep_debug=MACHDEP_DEBUG; 167 # define DPRINTF(x) do { if (machdep_debug) printf x ; } while(0) 168 #else 169 # define DPRINTF(x) 170 #endif 171 172 #ifndef CONSFREQ 173 # define CONSFREQ -1 /* inherit from firmware */ 174 #endif 175 #ifndef CONSPEED 176 # define CONSPEED 38400 177 #endif 178 #ifndef CONMODE 179 # define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) 180 #endif 181 #ifndef CONSADDR 182 # define CONSADDR RMIXL_IO_DEV_UART_1 183 #endif 184 185 int comcnfreq = CONSFREQ; 186 int comcnspeed = CONSPEED; 187 tcflag_t comcnmode = CONMODE; 188 bus_addr_t comcnaddr = (bus_addr_t)CONSADDR; 189 190 struct rmixl_config rmixl_configuration; 191 192 193 /* 194 * array of tested firmware versions 195 * if you find new ones and they work 196 * please add them 197 */ 198 static uint64_t rmiclfw_psb_versions[] = { 199 0x4958d4fb00000056ULL, 200 0x49a5a8fa00000056ULL, 201 0x4aacdb6a00000056ULL, 202 }; 203 #define RMICLFW_PSB_VERSIONS_LEN \ 204 (sizeof(rmiclfw_psb_versions)/sizeof(rmiclfw_psb_versions[0])) 205 206 /* 207 * kernel copies of firmware info 208 */ 209 static rmixlfw_info_t rmixlfw_info; 210 static rmixlfw_mmap_t rmixlfw_phys_mmap; 211 static rmixlfw_mmap_t rmixlfw_avail_mmap; 212 #define RMIXLFW_INFOP_LEGAL 0x8c000000 213 214 215 /* 216 * storage for fixed extent used to allocate physical address regions 217 * because extent(9) start and end values are u_long, they are only 218 * 32 bits on a 32 bit kernel, which is insuffucuent since XLS physical 219 * address is 40 bits wide. So the "physaddr" map stores regions 220 * in units of megabytes. 221 */ 222 static u_long rmixl_physaddr_storage[ 223 EXTENT_FIXED_STORAGE_SIZE(32)/sizeof(u_long) 224 ]; 225 226 /* For sysctl_hw. */ 227 extern char cpu_model[]; 228 229 /* Our exported CPU info; we can have only one. */ 230 struct cpu_info cpu_info_store; 231 232 /* Maps for VM objects. */ 233 struct vm_map *phys_map = NULL; 234 235 int physmem; /* Total physical memory */ 236 237 int netboot; /* Are we netbooting? */ 238 239 240 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 241 u_int mem_cluster_cnt; 242 243 244 void configure(void); 245 void mach_init(int, int32_t *, void *, int64_t); 246 static u_long rmixlfw_init(int64_t); 247 static u_long mem_clusters_init(rmixlfw_mmap_t *, rmixlfw_mmap_t *); 248 static void __attribute__((__noreturn__)) rmixl_exit(int); 249 static void rmixl_physaddr_init(void); 250 static u_int ram_seg_resv(phys_ram_seg_t *, u_int, u_quad_t, u_quad_t); 251 void rmixlfw_mmap_print(rmixlfw_mmap_t *); 252 253 254 /* 255 * safepri is a safe priority for sleep to set for a spin-wait during 256 * autoconfiguration or after a panic. Used as an argument to splx(). 257 */ 258 int safepri = MIPS1_PSL_LOWIPL; 259 260 /* 261 * Do all the stuff that locore normally does before calling main(). 262 */ 263 void 264 mach_init(int argc, int32_t *argv, void *envp, int64_t infop) 265 { 266 struct rmixl_config *rcp = &rmixl_configuration; 267 void *kernend; 268 u_long memsize; 269 u_int vm_cluster_cnt; 270 uint32_t r; 271 phys_ram_seg_t vm_clusters[VM_PHYSSEG_MAX]; 272 extern char edata[], end[]; 273 274 rmixl_mtcr(0, 1); /* disable all threads except #0 */ 275 276 r = rmixl_mfcr(0x300); 277 r &= ~__BIT(14); /* disabled Unaligned Access */ 278 rmixl_mtcr(0x300, r); 279 280 rmixl_mtcr(0x400, 0); /* enable MMU clock gating */ 281 /* set single MMU Thread Mode */ 282 /* TLB is partitioned (1 partition) */ 283 284 /* 285 * Clear the BSS segment. 286 */ 287 kernend = (void *)mips_round_page(end); 288 memset(edata, 0, (char *)kernend - edata); 289 290 /* 291 * Set up the exception vectors and CPU-specific function 292 * vectors early on. We need the wbflush() vector set up 293 * before comcnattach() is called (or at least before the 294 * first printf() after that is called). 295 * Also clears the I+D caches. 296 */ 297 mips_vector_init(); 298 299 memsize = rmixlfw_init(infop); 300 301 /* set the VM page size */ 302 uvm_setpagesize(); 303 304 physmem = btoc(memsize); 305 306 rmixl_obio_bus_mem_init(&rcp->rc_obio_memt, rcp); /* need for console */ 307 308 #if NCOM > 0 309 rmixl_com_cnattach(comcnaddr, comcnspeed, comcnfreq, 310 COM_TYPE_NORMAL, comcnmode); 311 #endif 312 313 printf("\nNetBSD/rmixl\n"); 314 printf("memsize = %#lx\n", memsize); 315 316 rmixl_physaddr_init(); 317 318 /* 319 * Obtain the cpu frequency 320 * Compute the number of ticks for hz. 321 * Compute the delay divisor. 322 * Double the Hz if this CPU runs at twice the 323 * external/cp0-count frequency 324 */ 325 curcpu()->ci_cpu_freq = rmixlfw_info.cpu_frequency; 326 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz; 327 curcpu()->ci_divisor_delay = 328 ((curcpu()->ci_cpu_freq + 500000) / 1000000); 329 if (mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT) 330 curcpu()->ci_cpu_freq *= 2; 331 332 /* 333 * Look at arguments passed to us and compute boothowto. 334 * - rmixl firmware gives us a 32 bit argv[i], so adapt 335 * by forcing sign extension in cast to (char *) 336 */ 337 boothowto = RB_AUTOBOOT; 338 for (int i = 1; i < argc; i++) { 339 for (char *cp = (char *)(intptr_t)argv[i]; *cp; cp++) { 340 int howto; 341 /* Ignore superfluous '-', if there is one */ 342 if (*cp == '-') 343 continue; 344 345 howto = 0; 346 BOOT_FLAG(*cp, howto); 347 if (howto != 0) 348 boothowto |= howto; 349 #ifdef DIAGNOSTIC 350 else 351 printf("bootflag '%c' not recognised\n", *cp); 352 #endif 353 } 354 } 355 #ifdef DIAGNOSTIC 356 printf("boothowto %#x\n", boothowto); 357 #endif 358 359 /* 360 * Reserve pages from the VM system. 361 * to maintain mem_clusters[] as a map of raw ram, 362 * copy into temporary table vm_clusters[] 363 * work on that and use it to feed vm_physload() 364 */ 365 KASSERT(sizeof(mem_clusters) == sizeof(vm_clusters)); 366 memcpy(&vm_clusters, &mem_clusters, sizeof(vm_clusters)); 367 vm_cluster_cnt = mem_cluster_cnt; 368 369 /* reserve 0..start..kernend pages */ 370 vm_cluster_cnt = ram_seg_resv(vm_clusters, vm_cluster_cnt, 371 0, round_page(MIPS_KSEG0_TO_PHYS(kernend))); 372 373 /* reserve reset exception vector page */ 374 /* should never be in our clusters anyway... */ 375 vm_cluster_cnt = ram_seg_resv(vm_clusters, vm_cluster_cnt, 376 MIPS_RESET_EXC_VEC, MIPS_RESET_EXC_VEC+NBPG); 377 378 /* 379 * Load vm_clusters[] into the VM system. 380 */ 381 for (u_int i=0; i < vm_cluster_cnt; i++) { 382 u_quad_t first, last; 383 384 first = trunc_page(vm_clusters[i].start); 385 last = round_page(vm_clusters[i].start + vm_clusters[i].size); 386 DPRINTF(("%s: %d: %#"PRIx64", %#"PRIx64"\n", 387 __func__, i, first, last)); 388 389 uvm_page_physload(atop(first), atop(last), atop(first), 390 atop(last), VM_FREELIST_DEFAULT); 391 } 392 393 /* 394 * Initialize error message buffer (at end of core). 395 */ 396 mips_init_msgbuf(); 397 398 pmap_bootstrap(); 399 400 /* 401 * Allocate uarea page for lwp0 and set it. 402 */ 403 mips_init_lwp0_uarea(); 404 405 #if defined(DDB) 406 if (boothowto & RB_KDB) 407 Debugger(); 408 #endif 409 } 410 411 /* 412 * ram_seg_resv - cut reserved regions out of segs, fragmenting as needed 413 * 414 * we simply build a new table of segs, then copy it back over the given one 415 * this is inefficient but simple and called only a few times 416 * 417 * note: 'last' here means 1st addr past the end of the segment (start+size) 418 */ 419 static u_int 420 ram_seg_resv(phys_ram_seg_t *segs, u_int nsegs, 421 u_quad_t resv_first, u_quad_t resv_last) 422 { 423 u_quad_t first, last; 424 int new_nsegs=0; 425 int resv_flag; 426 phys_ram_seg_t new_segs[VM_PHYSSEG_MAX]; 427 428 for (u_int i=0; i < nsegs; i++) { 429 resv_flag = 0; 430 first = trunc_page(segs[i].start); 431 last = round_page(segs[i].start + segs[i].size); 432 433 KASSERT(new_nsegs < VM_PHYSSEG_MAX); 434 if ((resv_first <= first) && (resv_last >= last)) { 435 /* whole segment is resverved */ 436 continue; 437 } 438 if ((resv_first > first) && (resv_first < last)) { 439 u_quad_t new_last; 440 441 /* 442 * reserved start in segment 443 * salvage the leading fragment 444 */ 445 resv_flag = 1; 446 new_last = last - (last - resv_first); 447 KASSERT (new_last > first); 448 new_segs[new_nsegs].start = first; 449 new_segs[new_nsegs].size = new_last - first; 450 new_nsegs++; 451 } 452 if ((resv_last > first) && (resv_last < last)) { 453 u_quad_t new_first; 454 455 /* 456 * reserved end in segment 457 * salvage the trailing fragment 458 */ 459 resv_flag = 1; 460 new_first = first + (resv_last - first); 461 KASSERT (last > (new_first + NBPG)); 462 new_segs[new_nsegs].start = new_first; 463 new_segs[new_nsegs].size = last - new_first; 464 new_nsegs++; 465 } 466 if (resv_flag == 0) { 467 /* 468 * nothing reserved here, take it all 469 */ 470 new_segs[new_nsegs].start = first; 471 new_segs[new_nsegs].size = last - first; 472 new_nsegs++; 473 } 474 475 } 476 477 memcpy(segs, new_segs, sizeof(new_segs)); 478 479 return new_nsegs; 480 } 481 482 /* 483 * create an extent for physical address space 484 * these are in units of MB for sake of compression (for sake of 32 bit kernels) 485 * allocate the regions where we have known functions (DRAM, IO, etc) 486 * what remains can be allocated as needed for other stuff 487 * e.g. to configure BARs that are not already initialized and enabled. 488 */ 489 static void 490 rmixl_physaddr_init(void) 491 { 492 struct extent *ext; 493 unsigned long start = 0UL; 494 unsigned long end = (__BIT(40) / (1024 * 1024)) -1; 495 u_long base; 496 u_long size; 497 uint32_t r; 498 499 ext = extent_create("physaddr", start, end, M_DEVBUF, 500 (void *)rmixl_physaddr_storage, sizeof(rmixl_physaddr_storage), 501 EX_NOWAIT | EX_NOCOALESCE); 502 503 if (ext == NULL) 504 panic("%s: extent_create failed", __func__); 505 506 /* 507 * grab regions per DRAM BARs 508 */ 509 for (u_int i=0; i < RMIXL_SBC_DRAM_NBARS; i++) { 510 r = RMIXL_IOREG_READ(RMIXL_SBC_DRAM_BAR(i)); 511 if ((r & RMIXL_DRAM_BAR_STATUS) == 0) 512 continue; /* not enabled */ 513 base = (u_long)(DRAM_BAR_TO_BASE((uint64_t)r) / (1024 * 1024)); 514 size = (u_long)(DRAM_BAR_TO_SIZE((uint64_t)r) / (1024 * 1024)); 515 516 DPRINTF(("%s: %d: %d: 0x%08x -- 0x%010lx:%lu MB\n", 517 __func__, __LINE__, i, r, base * (1024 * 1024), size)); 518 if (extent_alloc_region(ext, base, size, EX_NOWAIT) != 0) 519 panic("%s: extent_alloc_region(%p, %#lx, %#lx, %#x) " 520 "failed", __func__, ext, base, size, EX_NOWAIT); 521 } 522 523 /* 524 * grab regions per PCIe CFG, ECFG, IO, MEM BARs 525 */ 526 r = RMIXL_IOREG_READ(RMIXL_SBC_PCIE_CFG_BAR); 527 if ((r & RMIXL_PCIE_CFG_BAR_ENB) != 0) { 528 base = (u_long)(RMIXL_PCIE_CFG_BAR_TO_BA((uint64_t)r) 529 / (1024 * 1024)); 530 size = (u_long)RMIXL_PCIE_CFG_SIZE / (1024 * 1024); 531 DPRINTF(("%s: %d: %s: 0x%08x -- 0x%010lx:%ld MB\n", __func__, 532 __LINE__, "CFG", r, base * 1024 * 1024, size)); 533 if (extent_alloc_region(ext, base, size, EX_NOWAIT) != 0) 534 panic("%s: extent_alloc_region(%p, %#lx, %#lx, %#x) " 535 "failed", __func__, ext, base, size, EX_NOWAIT); 536 } 537 r = RMIXL_IOREG_READ(RMIXL_SBC_PCIE_ECFG_BAR); 538 if ((r & RMIXL_PCIE_ECFG_BAR_ENB) != 0) { 539 base = (u_long)(RMIXL_PCIE_ECFG_BAR_TO_BA((uint64_t)r) 540 / (1024 * 1024)); 541 size = (u_long)RMIXL_PCIE_ECFG_SIZE / (1024 * 1024); 542 DPRINTF(("%s: %d: %s: 0x%08x -- 0x%010lx:%ld MB\n", __func__, 543 __LINE__, "ECFG", r, base * 1024 * 1024, size)); 544 if (extent_alloc_region(ext, base, size, EX_NOWAIT) != 0) 545 panic("%s: extent_alloc_region(%p, %#lx, %#lx, %#x) " 546 "failed", __func__, ext, base, size, EX_NOWAIT); 547 } 548 r = RMIXL_IOREG_READ(RMIXL_SBC_PCIE_MEM_BAR); 549 if ((r & RMIXL_PCIE_MEM_BAR_ENB) != 0) { 550 base = (u_long)(RMIXL_PCIE_MEM_BAR_TO_BA((uint64_t)r) 551 / (1024 * 1024)); 552 size = (u_long)(RMIXL_PCIE_MEM_BAR_TO_SIZE((uint64_t)r) 553 / (1024 * 1024)); 554 DPRINTF(("%s: %d: %s: 0x%08x -- 0x%010lx:%ld MB\n", __func__, 555 __LINE__, "MEM", r, base * 1024 * 1024, size)); 556 if (extent_alloc_region(ext, base, size, EX_NOWAIT) != 0) 557 panic("%s: extent_alloc_region(%p, %#lx, %#lx, %#x) " 558 "failed", __func__, ext, base, size, EX_NOWAIT); 559 } 560 r = RMIXL_IOREG_READ(RMIXL_SBC_PCIE_IO_BAR); 561 if ((r & RMIXL_PCIE_IO_BAR_ENB) != 0) { 562 base = (u_long)(RMIXL_PCIE_IO_BAR_TO_BA((uint64_t)r) 563 / (1024 * 1024)); 564 size = (u_long)(RMIXL_PCIE_IO_BAR_TO_SIZE((uint64_t)r) 565 / (1024 * 1024)); 566 DPRINTF(("%s: %d: %s: 0x%08x -- 0x%010lx:%ld MB\n", __func__, 567 __LINE__, "IO", r, base * 1024 * 1024, size)); 568 if (extent_alloc_region(ext, base, size, EX_NOWAIT) != 0) 569 panic("%s: extent_alloc_region(%p, %#lx, %#lx, %#x) " 570 "failed", __func__, ext, base, size, EX_NOWAIT); 571 } 572 573 /* 574 * at this point all regions left in "physaddr" extent 575 * are unused holes in the physical adress space 576 * available for use as needed. 577 */ 578 rmixl_configuration.rc_phys_ex = ext; 579 #ifdef MACHDEP_DEBUG 580 extent_print(ext); 581 #endif 582 } 583 584 static u_long 585 rmixlfw_init(int64_t infop) 586 { 587 struct rmixl_config *rcp = &rmixl_configuration; 588 589 strcpy(cpu_model, "RMI XLS616ATX VIIA"); /* XXX */ 590 591 infop |= MIPS_KSEG0_START; 592 rmixlfw_info = *(rmixlfw_info_t *)(intptr_t)infop; 593 594 for (int i=0; i < RMICLFW_PSB_VERSIONS_LEN; i++) { 595 if (rmiclfw_psb_versions[i] == rmixlfw_info.psb_version) 596 goto found; 597 } 598 599 rcp->rc_io_pbase = RMIXL_IO_DEV_PBASE; 600 rmixl_putchar_init(rcp->rc_io_pbase); 601 602 #ifdef DIAGNOSTIC 603 rmixl_puts("\r\nWARNING: untested psb_version: "); 604 rmixl_puthex64(rmixlfw_info.psb_version); 605 rmixl_puts("\r\n"); 606 #endif 607 608 /* XXX trust and use MEMSIZE */ 609 mem_clusters[0].start = 0; 610 mem_clusters[0].size = MEMSIZE; 611 mem_cluster_cnt = 1; 612 return MEMSIZE; 613 614 found: 615 rcp->rc_io_pbase = MIPS_KSEG1_TO_PHYS(rmixlfw_info.io_base); 616 rmixl_putchar_init(rcp->rc_io_pbase); 617 #ifdef MACHDEP_DEBUG 618 rmixl_puts("\r\ninfop: "); 619 rmixl_puthex64((uint64_t)(intptr_t)infop); 620 #endif 621 #ifdef DIAGNOSTIC 622 rmixl_puts("\r\nrecognized psb_version: "); 623 rmixl_puthex64(rmixlfw_info.psb_version); 624 rmixl_puts("\r\n"); 625 #endif 626 627 return mem_clusters_init( 628 (rmixlfw_mmap_t *)(intptr_t)rmixlfw_info.psb_physaddr_map, 629 (rmixlfw_mmap_t *)(intptr_t)rmixlfw_info.avail_mem_map); 630 } 631 632 void 633 rmixlfw_mmap_print(rmixlfw_mmap_t *map) 634 { 635 #ifdef MACHDEP_DEBUG 636 for (uint32_t i=0; i < map->nmmaps; i++) { 637 rmixl_puthex32(i); 638 rmixl_puts(", "); 639 rmixl_puthex64(map->entry[i].start); 640 rmixl_puts(", "); 641 rmixl_puthex64(map->entry[i].size); 642 rmixl_puts(", "); 643 rmixl_puthex32(map->entry[i].type); 644 rmixl_puts("\r\n"); 645 } 646 #endif 647 } 648 649 /* 650 * mem_clusters_init 651 * 652 * initialize mem_clusters[] table based on memory address mapping 653 * provided by boot firmware. 654 * 655 * prefer avail_mem_map if we can, otherwise use psb_physaddr_map. 656 * these will be limited by MEMSIZE if it is configured. 657 * if neither are available, just use MEMSIZE. 658 */ 659 static u_long 660 mem_clusters_init( 661 rmixlfw_mmap_t *psb_physaddr_map, 662 rmixlfw_mmap_t *avail_mem_map) 663 { 664 rmixlfw_mmap_t *map = NULL; 665 const char *mapname; 666 uint64_t tmp; 667 uint64_t sz; 668 uint64_t sum; 669 u_int cnt; 670 #ifdef MEMSIZE 671 u_long memsize = MEMSIZE; 672 #endif 673 674 #ifdef MACHDEP_DEBUG 675 rmixl_puts("psb_physaddr_map: "); 676 rmixl_puthex64((uint64_t)(intptr_t)psb_physaddr_map); 677 rmixl_puts("\r\n"); 678 #endif 679 if (psb_physaddr_map != NULL) { 680 rmixlfw_phys_mmap = *psb_physaddr_map; 681 map = &rmixlfw_phys_mmap; 682 mapname = "psb_physaddr_map"; 683 rmixlfw_mmap_print(map); 684 } 685 #ifdef DIAGNOSTIC 686 else { 687 rmixl_puts("WARNING: no psb_physaddr_map\r\n"); 688 } 689 #endif 690 691 #ifdef MACHDEP_DEBUG 692 rmixl_puts("avail_mem_map: "); 693 rmixl_puthex64((uint64_t)(intptr_t)avail_mem_map); 694 rmixl_puts("\r\n"); 695 #endif 696 if (avail_mem_map != NULL) { 697 rmixlfw_avail_mmap = *avail_mem_map; 698 map = &rmixlfw_avail_mmap; 699 mapname = "avail_mem_map"; 700 rmixlfw_mmap_print(map); 701 } 702 #ifdef DIAGNOSTIC 703 else { 704 rmixl_puts("WARNING: no avail_mem_map\r\n"); 705 } 706 #endif 707 708 if (map == NULL) { 709 #ifndef MEMSIZE 710 rmixl_puts("panic: no firmware memory map, " 711 "must configure MEMSIZE\r\n"); 712 for(;;); /* XXX */ 713 #else 714 #ifdef DIAGNOSTIC 715 rmixl_puts("WARNING: no avail_mem_map, " 716 "using MEMSIZE\r\n"); 717 #endif 718 719 mem_clusters[0].start = 0; 720 mem_clusters[0].size = MEMSIZE; 721 mem_cluster_cnt = 1; 722 return MEMSIZE; 723 #endif /* MEMSIZE */ 724 } 725 726 #ifdef DIAGNOSTIC 727 rmixl_puts("using "); 728 rmixl_puts(mapname); 729 rmixl_puts("\r\n"); 730 #endif 731 #ifdef MACHDEP_DEBUG 732 rmixl_puts("memory clusters:\r\n"); 733 #endif 734 sum = 0; 735 cnt = 0; 736 for (uint32_t i=0; i < map->nmmaps; i++) { 737 if (map->entry[i].type != RMIXLFW_MMAP_TYPE_RAM) 738 continue; 739 mem_clusters[cnt].start = map->entry[i].start; 740 sz = map->entry[i].size; 741 sum += sz; 742 mem_clusters[cnt].size = sz; 743 #ifdef MACHDEP_DEBUG 744 rmixl_puthex32(i); 745 rmixl_puts(": "); 746 rmixl_puthex64(mem_clusters[cnt].start); 747 rmixl_puts(", "); 748 rmixl_puthex64(sz); 749 rmixl_puts(": "); 750 rmixl_puthex64(sum); 751 rmixl_puts("\r\n"); 752 #endif 753 #ifdef MEMSIZE 754 /* 755 * configurably limit memsize 756 */ 757 if (sum == memsize) 758 break; 759 if (sum > memsize) { 760 tmp = sum - memsize; 761 sz -= tmp; 762 sum -= tmp; 763 mem_clusters[cnt].size = sz; 764 break; 765 } 766 #endif 767 cnt++; 768 } 769 mem_cluster_cnt = cnt; 770 return sum; 771 } 772 773 void 774 consinit(void) 775 { 776 777 /* 778 * Everything related to console initialization is done 779 * in mach_init(). 780 */ 781 } 782 783 /* 784 * Allocate memory for variable-sized tables, 785 */ 786 void 787 cpu_startup() 788 { 789 vaddr_t minaddr, maxaddr; 790 char pbuf[9]; 791 792 /* 793 * Good {morning,afternoon,evening,night}. 794 */ 795 printf("%s%s", copyright, version); 796 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 797 printf("total memory = %s\n", pbuf); 798 799 /* 800 * Virtual memory is bootstrapped -- notify the bus spaces 801 * that memory allocation is now safe. 802 */ 803 rmixl_configuration.rc_mallocsafe = 1; 804 805 minaddr = 0; 806 /* 807 * Allocate a submap for physio. 808 */ 809 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 810 VM_PHYS_SIZE, 0, FALSE, NULL); 811 812 /* 813 * (No need to allocate an mbuf cluster submap. Mbuf clusters 814 * are allocated via the pool allocator, and we use XKSEG to 815 * map those pages.) 816 */ 817 818 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 819 printf("avail memory = %s\n", pbuf); 820 } 821 822 int waittime = -1; 823 824 void 825 cpu_reboot(int howto, char *bootstr) 826 { 827 828 /* Take a snapshot before clobbering any registers. */ 829 if (curproc) 830 savectx(curpcb); 831 832 if (cold) { 833 howto |= RB_HALT; 834 goto haltsys; 835 } 836 837 /* If "always halt" was specified as a boot flag, obey. */ 838 if (boothowto & RB_HALT) 839 howto |= RB_HALT; 840 841 boothowto = howto; 842 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 843 waittime = 0; 844 vfs_shutdown(); 845 846 /* 847 * If we've been adjusting the clock, the todr 848 * will be out of synch; adjust it now. 849 */ 850 resettodr(); 851 } 852 853 splhigh(); 854 855 if (howto & RB_DUMP) 856 dumpsys(); 857 858 haltsys: 859 doshutdownhooks(); 860 861 if (howto & RB_HALT) { 862 printf("\n"); 863 printf("The operating system has halted.\n"); 864 printf("Please press any key to reboot.\n\n"); 865 cnpollc(1); /* For proper keyboard command handling */ 866 cngetc(); 867 cnpollc(0); 868 } 869 870 printf("rebooting...\n\n"); 871 872 rmixl_exit(0); 873 } 874 875 /* 876 * goodbye world 877 */ 878 #define GPIO_CPU_RST 0xa0 /* XXX TMP */ 879 void __attribute__((__noreturn__)) 880 rmixl_exit(int howto) 881 { 882 /* use firmware callbak to reboot */ 883 void (*reset)(void) = (void *)(intptr_t)rmixlfw_info.warm_reset; 884 if (reset != 0) { 885 (*reset)(); 886 printf("warm reset callback failed, spinning...\n"); 887 } else { 888 printf("warm reset callback absent, spinning...\n"); 889 } 890 for (;;); 891 } 892