1/* $NetBSD: machdep.c,v 1.50 2011/04/04 20:37:49 dyoung Exp $ */ 2 3/*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Portions written by Garrett D'Amore for Itronix 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. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34/* 35 * Copyright (c) 1988 University of Utah. 36 * Copyright (c) 1992, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * the Systems Programming Group of the University of Utah Computer 41 * Science Department, The Mach Operating System project at 42 * Carnegie-Mellon University and Ralph Campbell. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 * 68 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 69 * from: Utah Hdr: machdep.c 1.63 91/04/24 70 */ 71 72#include <sys/cdefs.h> 73__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.50 2011/04/04 20:37:49 dyoung Exp $"); 74 75#include "opt_ddb.h" 76#include "opt_kgdb.h" 77 78#include "opt_memsize.h" 79#include "opt_modular.h" 80#include "opt_ethaddr.h" 81 82#include <sys/param.h> 83#include <sys/boot_flag.h> 84#include <sys/buf.h> 85#include <sys/device.h> 86#include <sys/kcore.h> 87#include <sys/kernel.h> 88#include <sys/ksyms.h> 89#include <sys/mount.h> 90#include <sys/reboot.h> 91#include <sys/systm.h> 92#include <sys/termios.h> 93 94#include <net/if.h> 95#include <net/if_ether.h> 96 97#include <uvm/uvm_extern.h> 98 99#include <dev/cons.h> 100 101#include "ksyms.h" 102 103#if NKSYMS || defined(DDB) || defined(MODULAR) 104#include <mips/db_machdep.h> 105#include <ddb/db_extern.h> 106#endif 107 108#include <mips/cache.h> 109#include <mips/locore.h> 110 111#include <machine/yamon.h> 112 113#include <evbmips/alchemy/board.h> 114 115#include <mips/alchemy/dev/aupcivar.h> 116#include <mips/alchemy/dev/aupcmciavar.h> 117#include <mips/alchemy/dev/auspivar.h> 118#include <mips/alchemy/include/aureg.h> 119#include <mips/alchemy/include/auvar.h> 120#include <mips/alchemy/include/aubusvar.h> 121 122#include "com.h" 123#if NCOM > 0 124 125int aucomcnrate = 0; 126#endif /* NAUCOM > 0 */ 127 128#include "ohci.h" 129 130/* Maps for VM objects. */ 131struct vm_map *phys_map = NULL; 132 133int physmem; /* # pages of physical memory */ 134int maxmem; /* max memory per process */ 135 136int mem_cluster_cnt; 137phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 138 139yamon_env_var *yamon_envp; 140struct mips_bus_space alchemy_cpuregt; 141 142void mach_init(int, char **, yamon_env_var *, u_long); /* XXX */ 143 144void 145mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize) 146{ 147 bus_space_handle_t sh; 148 void *kernend; 149 const char *cp; 150 int freqok, howto, i; 151 const struct alchemy_board *board; 152 153 extern char edata[], end[]; /* XXX */ 154 155 board = board_info(); 156 KASSERT(board != NULL); 157 158 /* clear the BSS segment */ 159 kernend = (void *)mips_round_page(end); 160 memset(edata, 0, (char *)kernend - edata); 161 162 /* set CPU model info for sysctl_hw */ 163 strcpy(cpu_model, board->ab_name); 164 165 /* save the yamon environment pointer */ 166 yamon_envp = envp; 167 168 /* Use YAMON callbacks for early console I/O */ 169 cn_tab = &yamon_promcd; 170 171 /* 172 * Set up the exception vectors and CPU-specific function 173 * vectors early on. We need the wbflush() vector set up 174 * before comcnattach() is called (or at least before the 175 * first printf() after that is called). 176 * Sets up mips_cpu_flags that may be queried by other 177 * functions called during startup. 178 * Also clears the I+D caches. 179 */ 180 mips_vector_init(NULL, false); 181 182 /* 183 * Set the VM page size. 184 */ 185 uvm_setpagesize(); 186 187 /* 188 * Use YAMON's CPU frequency if available. 189 */ 190 freqok = yamon_setcpufreq(1); 191 192 /* 193 * Initialize bus space tags. 194 */ 195 au_cpureg_bus_mem_init(&alchemy_cpuregt, &alchemy_cpuregt); 196 aubus_st = &alchemy_cpuregt; 197 198 /* 199 * Calibrate the timer if YAMON failed to tell us. 200 */ 201 if (!freqok) { 202 bus_space_map(aubus_st, PC_BASE, PC_SIZE, 0, &sh); 203 au_cal_timers(aubus_st, sh); 204 bus_space_unmap(aubus_st, sh, PC_SIZE); 205 } 206 207 /* 208 * Perform board-specific initialization. 209 */ 210 board->ab_init(); 211 212 /* 213 * Bring up the console. 214 */ 215#if NCOM > 0 216#ifdef CONSPEED 217 if (aucomcnrate == 0) 218 aucomcnrate = CONSPEED; 219#else /* !CONSPEED */ 220 /* 221 * Learn default console speed. We use the YAMON environment, 222 * though we could probably also figure it out by checking the 223 * aucom registers directly. 224 */ 225 if ((aucomcnrate == 0) && ((cp = yamon_getenv("modetty0")) != NULL)) 226 aucomcnrate = strtoul(cp, NULL, 0); 227 228 if (aucomcnrate == 0) { 229 printf("FATAL: `modetty0' YAMON variable not set. Set it\n"); 230 printf(" to the speed of the console and try again.\n"); 231 printf(" Or, build a kernel with the `CONSPEED' " 232 "option.\n"); 233 panic("mach_init"); 234 } 235#endif /* CONSPEED */ 236 237 /* 238 * Delay to allow firmware putchars to complete. 239 * FIFO depth * character time. 240 * character time = (1000000 / (defaultrate / 10)) 241 */ 242 delay(160000000 / aucomcnrate); 243 if (com_aubus_cnattach(UART0_BASE, aucomcnrate) != 0) 244 panic("mach_init: unable to initialize serial console"); 245 246#else /* NCOM > 0 */ 247 panic("mach_init: not configured to use serial console"); 248#endif /* NAUCOM > 0 */ 249 250 /* 251 * Look at arguments passed to us and compute boothowto. 252 */ 253 boothowto = RB_AUTOBOOT; 254#ifdef KADB 255 boothowto |= RB_KDB; 256#endif 257 for (i = 1; i < argc; i++) { 258 for (cp = argv[i]; *cp; cp++) { 259 /* Ignore superfluous '-', if there is one */ 260 if (*cp == '-') 261 continue; 262 263 howto = 0; 264 BOOT_FLAG(*cp, howto); 265 if (! howto) 266 printf("bootflag '%c' not recognised\n", *cp); 267 else 268 boothowto |= howto; 269 } 270 } 271 272 /* 273 * Determine the memory size. Use the `memsize' PMON 274 * variable. If that's not available, panic. 275 * 276 * Note: Reserve the first page! That's where the trap 277 * vectors are located. 278 */ 279 280#if defined(MEMSIZE) 281 memsize = MEMSIZE; 282#else 283 if (memsize == 0) { 284 if ((cp = yamon_getenv("memsize")) != NULL) 285 memsize = strtoul(cp, NULL, 0); 286 else { 287 printf("FATAL: `memsize' YAMON variable not set. Set it to\n"); 288 printf(" the amount of memory (in MB) and try again.\n"); 289 printf(" Or, build a kernel with the `MEMSIZE' " 290 "option.\n"); 291 panic("mach_init"); 292 } 293 } 294#endif /* MEMSIZE */ 295 printf("Memory size: 0x%08lx\n", memsize); 296 physmem = btoc(memsize); 297 298 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 299 mem_clusters[mem_cluster_cnt].size = 300 memsize - mem_clusters[mem_cluster_cnt].start; 301 mem_cluster_cnt++; 302 303 /* 304 * Load the rest of the available pages into the VM system. 305 */ 306 mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend, 307 mem_clusters, mem_cluster_cnt, NULL, 0); 308 309 /* 310 * Initialize message buffer (at end of core). 311 */ 312 mips_init_msgbuf(); 313 314 /* 315 * Initialize the virtual memory system. 316 */ 317 pmap_bootstrap(); 318 319 /* 320 * Allocate uarea page for lwp0 and set it. 321 */ 322 mips_init_lwp0_uarea(); 323 324 /* 325 * Initialize debuggers, and break into them, if appropriate. 326 */ 327#ifdef DDB 328 if (boothowto & RB_KDB) 329 Debugger(); 330#endif 331} 332 333void 334consinit(void) 335{ 336 337 /* 338 * Everything related to console initialization is done 339 * in mach_init(). 340 */ 341} 342 343void 344cpu_startup(void) 345{ 346 char pbuf[9]; 347 vaddr_t minaddr, maxaddr; 348#ifdef DEBUG 349 extern int pmapdebug; /* XXX */ 350 int opmapdebug = pmapdebug; 351 352 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 353#endif 354 355 /* 356 * Good {morning,afternoon,evening,night}. 357 */ 358 printf("%s%s", copyright, version); 359 printf("%s\n", cpu_model); 360 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 361 printf("total memory = %s\n", pbuf); 362 363 minaddr = 0; 364 365 /* 366 * Allocate a submap for physio 367 */ 368 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 369 VM_PHYS_SIZE, 0, false, NULL); 370 371 /* 372 * No need to allocate an mbuf cluster submap. Mbuf clusters 373 * are allocated via the pool allocator, and we use KSEG to 374 * map those pages. 375 */ 376 377#ifdef DEBUG 378 pmapdebug = opmapdebug; 379#endif 380 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 381 printf("avail memory = %s\n", pbuf); 382} 383 384void 385cpu_reboot(int howto, char *bootstr) 386{ 387 static int waittime = -1; 388 const struct alchemy_board *board; 389 390 /* Take a snapshot before clobbering any registers. */ 391 savectx(curpcb); 392 393 board = board_info(); 394 KASSERT(board != NULL); 395 396 /* If "always halt" was specified as a boot flag, obey. */ 397 if (boothowto & RB_HALT) 398 howto |= RB_HALT; 399 400 boothowto = howto; 401 402 /* If system is cold, just halt. */ 403 if (cold) { 404 boothowto |= RB_HALT; 405 goto haltsys; 406 } 407 408 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 409 waittime = 0; 410 411 /* 412 * Synchronize the disks.... 413 */ 414 vfs_shutdown(); 415 416 /* 417 * If we've been adjusting the clock, the todr 418 * will be out of synch; adjust it now. 419 */ 420 resettodr(); 421 } 422 423 /* Disable interrupts. */ 424 splhigh(); 425 426 if (boothowto & RB_DUMP) 427 dumpsys(); 428 429 haltsys: 430 /* Run any shutdown hooks. */ 431 doshutdownhooks(); 432 433 pmf_system_shutdown(boothowto); 434 435 if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN) 436 if (board && board->ab_poweroff) 437 board->ab_poweroff(); 438 439 /* 440 * YAMON may autoboot (depending on settings), and we cannot pass 441 * flags to it (at least I haven't figured out how to yet), so 442 * we "pseudo-halt" now. 443 */ 444 if (boothowto & RB_HALT) { 445 printf("\n"); 446 printf("The operating system has halted.\n"); 447 printf("Please press any key to reboot.\n\n"); 448 cnpollc(1); /* For proper keyboard command handling */ 449 cngetc(); 450 cnpollc(0); 451 } 452 453 printf("reseting board...\n\n"); 454 455 /* 456 * Try to use board-specific reset logic, which might involve a better 457 * hardware reset. 458 */ 459 if (board->ab_reboot) 460 board->ab_reboot(); 461 462#if 1 463 /* XXX 464 * For some reason we are leaving the ethernet MAC in a state where 465 * YAMON isn't happy with it. So just call the reset vector (grr, 466 * Alchemy YAMON doesn't have a "reset" command). 467 */ 468 mips_icache_sync_all(); 469 mips_dcache_wbinv_all(); 470 __asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC)); 471#else 472 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 473 yamon_exit(boothowto); 474 printf("Oops, back from yamon_exit()\n\nSpinning..."); 475#endif 476 for (;;) 477 /* spin forever */ ; /* XXX */ 478 /*NOTREACHED*/ 479} 480 481/* 482 * Export our interrupt map function so aupci can find it. 483 */ 484int 485aupci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 486{ 487 const struct alchemy_board *board; 488 489 board = board_info(); 490 if (board->ab_pci_intr_map != NULL) 491 return (board->ab_pci_intr_map(pa, ihp)); 492 return 1; 493} 494 495struct aupcmcia_machdep * 496aupcmcia_machdep(void) 497{ 498 const struct alchemy_board *board; 499 500 board = board_info(); 501 return (board->ab_pcmcia); 502} 503 504const struct auspi_machdep * 505auspi_machdep(bus_addr_t ba) 506{ 507 const struct alchemy_board *board; 508 509 board = board_info(); 510 if (board->ab_spi != NULL) 511 return (board->ab_spi(ba)); 512 return NULL; 513} 514