1139825Simp/* $NetBSD: machdep.c,v 1.20 2024/03/05 14:15:29 thorpej Exp $ */ 222521Sdyson 31541Srgrimes/* 41541Srgrimes * Copyright (c) 1988 University of Utah. 51541Srgrimes * Copyright (c) 1992, 1993 61541Srgrimes * The Regents of the University of California. All rights reserved. 71541Srgrimes * 81541Srgrimes * This code is derived from software contributed to Berkeley by 91541Srgrimes * the Systems Programming Group of the University of Utah Computer 101541Srgrimes * Science Department, The Mach Operating System project at 111541Srgrimes * Carnegie-Mellon University and Ralph Campbell. 121541Srgrimes * 131541Srgrimes * Redistribution and use in source and binary forms, with or without 141541Srgrimes * modification, are permitted provided that the following conditions 151541Srgrimes * are met: 161541Srgrimes * 1. Redistributions of source code must retain the above copyright 171541Srgrimes * notice, this list of conditions and the following disclaimer. 181541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 191541Srgrimes * notice, this list of conditions and the following disclaimer in the 201541Srgrimes * documentation and/or other materials provided with the distribution. 211541Srgrimes * 3. Neither the name of the University nor the names of its contributors 221541Srgrimes * may be used to endorse or promote products derived from this software 231541Srgrimes * without specific prior written permission. 241541Srgrimes * 251541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3422521Sdyson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351541Srgrimes * SUCH DAMAGE. 361541Srgrimes * 37116192Sobrien * @(#)machdep.c 8.3 (Berkeley) 1/12/94 38116192Sobrien * from: Utah Hdr: machdep.c 1.63 91/04/24 39116192Sobrien */ 4013260Swollman 4174433Srwatson#include <sys/cdefs.h> 4213260Swollman__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.20 2024/03/05 14:15:29 thorpej Exp $"); 431541Srgrimes 4496010Sjeff#include "opt_ddb.h" 451541Srgrimes 4684811Sjhb#include <sys/param.h> 471541Srgrimes#include <sys/systm.h> 4830285Sphk#include <sys/extent.h> 4971576Sjasone#include <sys/kernel.h> 501541Srgrimes#include <sys/buf.h> 5159241Srwatson#include <sys/mbuf.h> 521541Srgrimes#include <sys/reboot.h> 531541Srgrimes#include <sys/mount.h> 5430285Sphk#include <sys/kcore.h> 551541Srgrimes#include <sys/boot_flag.h> 5679561Siedowse#include <sys/ksyms.h> 5779561Siedowse#include <sys/proc.h> 5879561Siedowse#include <sys/device.h> 5979561Siedowse#include <sys/cpu.h> 60163841Spjd 61163841Spjd#include <uvm/uvm_extern.h> 62163841Spjd 631541Srgrimes#include <dev/cons.h> 641541Srgrimes 651541Srgrimes#include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 661541Srgrimes 671541Srgrimes#include <mips/cache.h> 681541Srgrimes#include <machine/psl.h> 691541Srgrimes#include <machine/autoconf.h> 701541Srgrimes#include <emips/stand/common/prom_iface.h> 7183366Sjulian#include <machine/sysconf.h> 721541Srgrimes#include <machine/bootinfo.h> 731541Srgrimes#include <machine/locore.h> 7422521Sdyson#include <emips/emips/machdep.h> 7522521Sdyson#include <machine/emipsreg.h> 7683366Sjulian 7798542Smckusick#define _EMIPS_BUS_DMA_PRIVATE 7898542Smckusick#include <machine/bus.h> 79216792Skib 80156451Stegge#if NKSYMS || defined(DDB) || defined(MODULAR) 811541Srgrimes#include <machine/db_machdep.h> 82156451Stegge#include <ddb/db_extern.h> 8322521Sdyson#endif 8422521Sdyson 8522521Sdysonvaddr_t iospace; 8622521Sdysonvsize_t iospace_size = 64 * 1024; /* BUGBUG make it an option? */ 8722521Sdyson 88163841Spjd#include "ksyms.h" 89163841Spjd 90163841Spjd/* 91235626Smckusick * Extent map to manage I/O register space. We allocate storage for 92235626Smckusick * 32 regions in the map. iomap_ex_malloc_safe will indicate that it's 93235626Smckusick * safe to use malloc() to dynamically allocate region descriptors in 94235626Smckusick * case we run out. 95235626Smckusick */ 96235626Smckusickstatic long iomap_ex_storage[EXTENT_FIXED_STORAGE_SIZE(32) / sizeof(long)]; 97235626Smckusickstatic struct extent *iomap_ex; 98235626Smckusickstatic int iomap_ex_malloc_safe; 99158382Stegge 100183070Skib/* maps for VM objects */ 101156560Steggestruct vm_map *phys_map = NULL; 102156560Stegge 103156560Steggeint systype; /* mother board type */ 104156560Steggechar *bootinfo = NULL; /* pointer to bootinfo structure */ 105156560Steggeint cpuspeed = 30; /* approx # instr per usec. */ 106156560Steggeintptr_t physmem_boardmax; /* {model,SIMM}-specific bound on physmem */ 107156560Steggeint mem_cluster_cnt; 108156560Steggephys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 109156560Stegge 110156560Steggevoid mach_init (int, char *[], int, intptr_t, u_int, char *); /* XXX */ 111156560Stegge 112156560Stegge/* Motherboard or system-specific initialization vector */ 113156560Steggestatic void unimpl_bus_reset(void); 114156560Steggestatic void unimpl_cons_init(void); 115156560Steggestatic void unimpl_iointr(uint32_t, vaddr_t, uint32_t); 116156560Steggestatic void unimpl_intr_establish(device_t, void *, int, 117156560Stegge int (*)(void *, void *), void *); 118156560Steggestatic int unimpl_memsize(void *); 119156560Stegge 120156560Steggestruct platform platform = { 121156560Stegge "iobus not set", 122156560Stegge unimpl_bus_reset, 123156560Stegge unimpl_cons_init, 124156560Stegge unimpl_iointr, 125156560Stegge unimpl_intr_establish, 126156560Stegge unimpl_memsize 127158382Stegge}; 128209717Sjeff 129209717Sjeffextern char *esym; /* XXX */ 130209717Sjeffextern struct consdev promcd; /* XXX */ 131223769Sjeffextern const struct callback *callv; 132223769Sjeffextern const struct callback callvec; 133223769Sjeff 134223769Sjeff/* 1351541Srgrimes * Do all the stuff that locore normally does before calling main(). 1361541Srgrimes * The first 4 arguments are passed by PROM monitor, and remaining two 13798788Smckusick * are built on temporary stack by our boot loader. 1381541Srgrimes */ 13974433Srwatsonvoid 140102774Srwatsonmach_init(int argc, char *argv[], int code, intptr_t cv, u_int bim, char *bip) 14159241Srwatson{ 14274548Smckusick char *cp; 14374548Smckusick const char *bootinfo_msg; 14474548Smckusick u_long first, last; 14574548Smckusick int i, howtoboot; 14674548Smckusick#if NKSYMS || defined(DDB) || defined(MODULAR) 14774548Smckusick void *ssym = 0; 148132775Skan struct btinfo_symtab *bi_syms; 1491541Srgrimes#endif 1501541Srgrimes void *kernend; 151132775Skan extern char edata[], end[]; /* XXX */ 1521541Srgrimes 15374548Smckusick /* Set up bootinfo structure looking at stack. */ 15474548Smckusick if (bim == BOOTINFO_MAGIC) { 15530474Sphk struct btinfo_magic *bi_magic; 1561541Srgrimes 15762976Smckusick bootinfo = bip; 15862976Smckusick bi_magic = lookup_bootinfo(BTINFO_MAGIC); 159156451Stegge if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 160156451Stegge bootinfo_msg = 161156451Stegge "invalid magic number in bootinfo structure.\n"; 16262976Smckusick else 16362976Smckusick bootinfo_msg = NULL; 164156451Stegge } else 165156451Stegge bootinfo_msg = "invalid bootinfo pointer (old bootblocks?)\n"; 166156451Stegge 16762976Smckusick /* 16862976Smckusick * Look at arguments passed to us and compute boothowto. 16962976Smckusick * Do it before we decide to keep symbols. 17022521Sdyson * NB: "boothowto" is in the BSS. 1711541Srgrimes */ 1721541Srgrimes howtoboot = 0; 1731541Srgrimes#ifdef KADB 1741541Srgrimes howtoboot |= RB_KDB; 17522521Sdyson#endif 176140936Sphk for (i = 1; i < argc; i++) { 177156451Stegge for (cp = argv[i]; *cp; cp++) { 178156451Stegge switch (*cp) { 1791541Srgrimes 1801541Srgrimes#define RB_NOSYMBOLS 0x10000000 1811541Srgrimes case 'e': /* empty the symtable */ 182220985Skib howtoboot |= RB_NOSYMBOLS; 183220985Skib break; 184220985Skib 185220985Skib case 'n': /* ask for names */ 186220985Skib howtoboot |= RB_ASKNAME; 187220985Skib break; 188220985Skib 189220985Skib case 'N': /* don't ask for names */ 190220985Skib howtoboot &= ~RB_ASKNAME; 191220985Skib break; 192220985Skib 193220985Skib default: 194220985Skib BOOT_FLAG(*cp, howtoboot); /* see sys/boot_flag.h */ 195220985Skib break; 196220985Skib } 197220985Skib } 198220985Skib } 199220985Skib 200220985Skib /* clear the BSS segment */ 201220985Skib#if NKSYMS || defined(DDB) || defined(MODULAR) 202220985Skib bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 203220985Skib 204220985Skib /* Was it a valid bootinfo symtab info? */ 205220985Skib if ((bi_syms != NULL) && (!(howtoboot & RB_NOSYMBOLS))) { 206220985Skib ssym = (void *)(intptr_t)bi_syms->ssym; 2071541Srgrimes esym = (void *)(intptr_t)bi_syms->esym; 2081541Srgrimes kernend = (void *)mips_round_page(esym); 2091541Srgrimes memset(edata, 0, end - edata); 2101541Srgrimes } else 21130285Sphk#endif 21230285Sphk { 21330285Sphk kernend = (char *)mips_round_page(end); 21483366Sjulian /* should be done by bootloader? */ 21530285Sphk memset(edata, 0, (char *)kernend - (char *)edata); 2161541Srgrimes } 21796506Sphk 21898542Smckusick /* Initialize callv so we can do PROM output... */ 21998542Smckusick callv = (code == PROM_MAGIC) ? (void *)cv : &callvec; 2201541Srgrimes 221220985Skib /* Use PROM console output until we initialize a console driver. */ 222220985Skib cn_tab = &promcd; 223170991Skib 22437363Sbde#if 1 225170991Skib if (bootinfo_msg != NULL) 2261541Srgrimes printf(bootinfo_msg); 22730418Sphk#endif 22830418Sphk uvm_md_init(); 229143562Sphk 230220985Skib /* 23130418Sphk * Copy exception-dispatch code down to exception vector. 232143743Sjeff * Initialize locore-function vector. 233143743Sjeff * Clear out the I and D caches. 234143743Sjeff */ 235143743Sjeff mips_vector_init(NULL, false); 236143743Sjeff 237143743Sjeff /* 238108313Sphk * We know the CPU type now. Initialize our DMA tags (might 2391541Srgrimes * need this early, for certain types of console devices!!). 2401541Srgrimes */ 241 emips_bus_dma_init(); 242 243 /* Look at argv[0] and compute bootdev */ 244 makebootdev(argv[0]); 245 246 boothowto = howtoboot & ~RB_NOSYMBOLS; 247 248 /* 249 * Check to see if a mini-root was loaded into memory. It resides 250 * at the start of the next page just after the end of BSS. 251 */ 252 if (boothowto & RB_MINIROOT) 253 kernend = (char *)kernend 254 + round_page(mfs_initminiroot(kernend)); 255 256#if NKSYMS || defined(DDB) || defined(MODULAR) 257 /* init symbols if present */ 258 if (esym) { 259 ksyms_addsyms_elf((char *)esym - (char *)ssym, ssym, esym); 260 } 261#endif 262#ifdef DDB 263 if (boothowto & RB_KDB) 264 Debugger(); 265#endif 266 267 /* 268 * Initialize physmem_boardmax; assume no SIMM-bank limits. 269 * Adjust later in model-specific code if necessary. 270 */ 271 physmem_boardmax = MIPS_MAX_MEM_ADDR; 272 273 /* 274 * Determine what model of computer we are running on. 275 */ 276 systype = ((prom_systype() >> 16) & 0xff); 277 if (systype >= nsysinit) { 278 platform_not_supported(); 279 /* NOTREACHED */ 280 } 281 282 /* Machine specific initialization. */ 283 (*sysinit[systype].init)(); 284 285 /* Find out how much memory is available. */ 286 physmem = (*platform.memsize)(kernend); 287 288 /* 289 * Load the rest of the available pages into the VM system. 290 * NB: The kernel can span multiple segments. 291 */ 292 for (i = 0, physmem = 0; i < mem_cluster_cnt; ++i) { 293 first = mem_clusters[i].start; 294 if (first < round_page(MIPS_KSEG0_TO_PHYS(kernend))) 295 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 296 last = mem_clusters[i].start + mem_clusters[i].size; 297 physmem += atop(mem_clusters[i].size); 298 299 /* if the kernel spans multiple segments (does on ML40x) */ 300 if (last <= first) 301 continue; 302 303 uvm_page_physload(atop(first), atop(last), atop(first), 304 atop(last), VM_FREELIST_DEFAULT); 305 } 306 307 /* 308 * Initialize error message buffer (at end of core). 309 */ 310 mips_init_msgbuf(); 311 312 /* 313 * Initialize the virtual memory system. 314 */ 315 iospace = pmap_limits.virtual_start; 316 pmap_limits.virtual_start += iospace_size; 317 pmap_bootstrap(); 318 319 mips_init_lwp0_uarea(); 320} 321 322void 323mips_machdep_cache_config(void) 324{ 325} 326 327void 328consinit(void) 329{ 330 /* 331 * Init I/O memory extent map. Must be done before cninit() 332 * is called; we may want to use iospace in the console routines. 333 */ 334 KASSERT(iospace != 0); 335 iomap_ex = extent_create("iomap", iospace, 336 iospace + iospace_size - 1, 337 (void *) iomap_ex_storage, sizeof(iomap_ex_storage), 338 EX_NOCOALESCE|EX_NOWAIT); 339 340 /* 341 * Up until now we have kept the TLB disabled, 342 * and that allowed the "PROM" to work. 343 * Specifically, romputc() and the debugger's getc() functions worked. 344 * Now is the last chance we get to turn it on. 345 * That means no more console I/O until autoconf() [sigh!], or.. 346 * The platform-specific code will have to map [1:1 probably] 347 * the I/O registers. 348 */ 349 register_t s = mips_cp0_status_read(); 350 s &= ~MIPS_SR_TS; 351 mips_cp0_status_write(s); 352 353 (*platform.cons_init)(); 354 355 /* 356 * Do NOT call cninit(); It will clobber cn_tab using constab[] 357 * which we do not use 358 */ 359} 360 361/* 362 * Allocates a virtual range suitable for mapping in physical memory. 363 * Uses resource maps when allocating space, which is allocated from 364 * the IOMAP submap. SIZE is a linear range (NOT vax-pages like the VAX). 365 * If the page requested is bigger than a logical page, space is 366 * allocated from the kernel map instead. 367 */ 368vaddr_t 369mips_map_physmem(paddr_t phys, vsize_t size) 370{ 371 vaddr_t addr; 372 int error; 373 static int warned = 0; 374 375 size += phys & PAGE_MASK; 376 if (size >= PAGE_SIZE) { 377 addr = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY); 378 if (addr == 0) 379 panic("mips_map_physmem: kernel map full"); 380 } else { 381 error = extent_alloc(iomap_ex, size, PAGE_SIZE, 0, 382 EX_FAST | EX_NOWAIT | 383 (iomap_ex_malloc_safe ? EX_MALLOCOK : 0), (u_long *)&addr); 384 if (error) { 385 if (warned++ == 0) /* Warn only once */ 386 printf("mips_map_physmem: iomap too small"); 387 return 0; 388 } 389 } 390 ioaccess(addr, phys, size); 391#ifdef PHYSMEMDEBUG 392 printf("mips_map_physmem: alloc'ed %x bytes for paddr %x, at %x\n", 393 size, phys, addr); 394#endif 395 return addr | (phys & PAGE_MASK); 396} 397 398/* 399 * Unmaps the previous mapped (addr, size) pair. 400 */ 401void 402mips_unmap_physmem(vaddr_t addr, vsize_t size) 403{ 404#ifdef PHYSMEMDEBUG 405 printf("mips_unmap_physmem: unmapping %x bytes at addr %x\n", 406 size, addr); 407#endif 408 size += addr & PAGE_MASK; 409 addr &= ~PAGE_MASK; 410 411 iounaccess(addr, size); 412 if (size >= PAGE_SIZE) 413 uvm_km_free(kernel_map, addr, size, UVM_KMF_VAONLY); 414 else if (extent_free(iomap_ex, addr, size, 415 EX_NOWAIT | (iomap_ex_malloc_safe ? EX_MALLOCOK : 0))) 416 printf("mips_unmap_physmem: addr 0x%llx size %llx: " 417 "can't free region\n", (long long)addr, (long long)size); 418} 419 420/* 421 * Machine-dependent startup code: allocate memory for variable-sized 422 * tables. 423 */ 424void 425cpu_startup(void) 426{ 427 vaddr_t minaddr, maxaddr; 428 char pbuf[9]; 429#ifdef DEBUG 430 extern int pmapdebug; /* XXX */ 431 int opmapdebug = pmapdebug; 432 433 pmapdebug = 0; 434#endif 435 436 /* 437 * Good {morning,afternoon,evening,night}. 438 */ 439 printf("%s%s", copyright, version); 440 printf("%s\n", cpu_getmodel()); 441 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 442 printf("total memory = %s\n", pbuf); 443 444 minaddr = 0; 445 446 /* 447 * Allocate a submap for physio 448 */ 449 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 450 VM_PHYS_SIZE, 0, false, NULL); 451 452 /* 453 * No need to allocate an mbuf cluster submap. Mbuf clusters 454 * are allocated via the pool allocator, and we use KSEG to 455 * map those pages. 456 */ 457 458 iomap_ex_malloc_safe = 1; 459 460#ifdef DEBUG 461 pmapdebug = opmapdebug; 462#endif 463 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 464 printf("avail memory = %s\n", pbuf); 465} 466 467/* 468 * Look up information in bootinfo of boot loader. 469 */ 470void * 471lookup_bootinfo(int type) 472{ 473 struct btinfo_common *bt; 474 char *help = bootinfo; 475 476 /* Check for a bootinfo record first. */ 477 if (help == NULL) 478 return (NULL); 479 480 do { 481 bt = (struct btinfo_common *)help; 482 if (bt->type == type) 483 return ((void *)help); 484 help += bt->next; 485 } while (bt->next != 0 && 486 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 487 488 return (NULL); 489} 490 491void 492cpu_reboot(volatile int howto, /* XXX volatile to keep gcc happy */ 493 char *bootstr) 494{ 495 496 /* take a snap shot before clobbering any registers */ 497 if (curlwp) 498 savectx(curpcb); 499 500#ifdef DEBUG 501 if (panicstr) 502 stacktrace(); 503#endif 504 505 /* If system is cold, just halt. */ 506 if (cold) { 507 howto |= RB_HALT; 508 goto haltsys; 509 } 510 511 /* If "always halt" was specified as a boot flag, obey. */ 512 if ((boothowto & RB_HALT) != 0) 513 howto |= RB_HALT; 514 515 boothowto = howto; 516 if ((howto & RB_NOSYNC) == 0) { 517 /* 518 * Synchronize the disks.... 519 */ 520 vfs_shutdown(); 521 } 522 523 /* Disable interrupts. */ 524 splhigh(); 525 526 /* If rebooting and a dump is requested do it. */ 527 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 528 dumpsys(); 529 530haltsys: 531 /* run any shutdown hooks */ 532 doshutdownhooks(); 533 534 pmf_system_shutdown(boothowto); 535 536 /* Finally, halt/reboot the system. */ 537 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 538 539 prom_halt(howto); 540 for (;;) ; 541 /*NOTREACHED*/ 542} 543 544#if defined(MIPS_4GB_PHYSICAL_MEMORY) 545#define trim_memory(n) n 546#else 547#if 0 548#define TOO_MUCH (MIPS_PHYS_MASK+1) 549#else 550#define TOO_MUCH (2*64*1024*1024) 551#endif 552u_long trim_memory(uint32_t nbytes);/*cheat*/ 553u_long trim_memory(uint32_t nbytes) 554{ 555 int i; 556 u_long first, last; 557 558 nbytes *= 4096; 559 if (nbytes <= TOO_MUCH) 560 return nbytes; 561 562 /* We have more memory than we can handle */ 563 564 mem_clusters[mem_cluster_cnt].start = 0;/* sentinel record */ 565 mem_clusters[mem_cluster_cnt].size = 0; 566 for (i = 0; i < mem_cluster_cnt;) { 567 first = mem_clusters[i].start; 568 last = mem_clusters[i].start + mem_clusters[i].size; 569 570 if (first > TOO_MUCH) { 571 printf("Too much memory, ignoring memory " 572 "range %08lx..%08lx\n", first, last); 573 memcpy(mem_clusters+i,mem_clusters+i+1, 574 (sizeof(mem_clusters[0])*(mem_cluster_cnt-i))); 575 mem_cluster_cnt--; 576 continue; 577 } 578 579 if (last > TOO_MUCH) { 580 last = TOO_MUCH; 581 printf("Too much memory in cluster %d, trimming " 582 "memory to range %08lx..%08lx\n", 583 i, first, last); 584 mem_clusters[i].size = last - mem_clusters[i].start; 585 } 586 i++; 587 } 588 return TOO_MUCH; 589} 590#endif 591 592/* 593 * Find out how much memory is available by testing memory. 594 */ 595int 596memsize_scan(void *first) 597{ 598 int i, mem; 599 char *cp; 600 601 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 602 cp = (char *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 603 while (cp < (char *)physmem_boardmax) { 604 int j; 605 if (badaddr(cp, 4)) 606 break; 607 i = *(int *)cp; 608 j = ((int *)cp)[4]; 609 *(int *)cp = 0xa5a5a5a5; 610 /* 611 * Data will persist on the bus if we read it right away. 612 * Have to be tricky here. 613 */ 614 ((int *)cp)[4] = 0x5a5a5a5a; 615 wbflush(); 616 if (*(int *)cp != 0xa5a5a5a5) 617 break; 618 *(int *)cp = i; 619 ((int *)cp)[4] = j; 620 cp += PAGE_SIZE; 621 mem++; 622 } 623 624 /* 625 * Now that we know how much memory we have, initialize the 626 * mem cluster array. 627 */ 628 mem_clusters[0].start = 0; /* XXX is this correct? */ 629 mem_clusters[0].size = ctob(mem); 630 mem_cluster_cnt = 1; 631 632 /* clear any memory error conditions possibly caused by probe */ 633 (*platform.bus_reset)(); 634 return (mem); 635} 636 637/* 638 * Find out how much memory is available by testing memory, starting at first. 639 * Returns the total number of pages. 640 */ 641int 642memsize_pmt(void * first) 643{ 644 int i, mem; 645 struct _Pmt *Pmt = ThePmt; 646 struct _Sram *ram; 647 uint32_t addr, len; 648 649 /* 650 * Build the RAM memory map from the PMT. 651 */ 652 mem = 0; 653 for (i = 0; i < VM_PHYSSEG_MAX; Pmt--) { 654 uint16_t tag = Pmt->Tag; 655 656 if (tag == PMTTAG_END_OF_TABLE) 657 break; 658 659 if ((tag != PMTTAG_SRAM) && (tag != PMTTAG_DDRAM)) 660 continue; 661 662 /* 663 * Got a memory controller segment, 664 * scan all the controllers in it 665 */ 666 ram = (struct _Sram *)(Pmt->TopOfPhysicalAddress << 16); 667 668 for (;(ram->BaseAddressAndTag & SRAMBT_TAG) == tag;) { 669 addr = ram->BaseAddressAndTag & SRAMBT_BASE; 670 len = ram->Control & SRAMST_SIZE; 671 672 mem_clusters[i].start = addr; 673 mem_clusters[i].size = len; 674 printf("memory segment %2d start %08lx size %08lx\n", i, 675 (long)mem_clusters[i].start, 676 (long)mem_clusters[i].size); 677 i++; 678 mem += len; 679 680 /* SRAM and DDRAM have different sizes */ 681 ram = (tag == PMTTAG_SRAM) ? ram+1 : ram+2; 682 } 683 } 684 mem_cluster_cnt = i; 685 686 return trim_memory(btoc(mem)); 687} 688/* 689 * Ensure all platform vectors are always initialized. 690 */ 691static void 692unimpl_bus_reset(void) 693{ 694 695 panic("sysconf.init didn't set bus_reset"); 696} 697 698static void 699unimpl_cons_init(void) 700{ 701 702 panic("sysconf.init didn't set cons_init"); 703} 704 705static void 706unimpl_iointr(uint32_t status, vaddr_t pc, uint32_t ipending) 707{ 708 709 panic("sysconf.init didn't set intr"); 710} 711 712static void 713unimpl_intr_establish(device_t dev, void *cookie, int level, 714 int (*handler) (void *,void *), void *arg) 715{ 716 717 panic("sysconf.init didn't set intr_establish"); 718} 719 720static int 721unimpl_memsize(void * first) 722{ 723 724 panic("sysconf.init didn't set memsize"); 725} 726 727/* 728 * Wait "n" microseconds. 729 */ 730void 731delay(int n) 732{ 733 734 DELAY(n); 735} 736