machdep.c revision 1.10
1/* $NetBSD: machdep.c,v 1.10 2009/02/13 22:41:01 apb Exp $ */ 2 3/*- 4 * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or 8 * without modification, are permitted provided that the following 9 * conditions are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 3. The names of the authors may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 */ 33/* 34 * Copyright (c) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department, The Mach Operating System project at 40 * Carnegie-Mellon University and Ralph Campbell. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 67 * from: Utah Hdr: machdep.c 1.63 91/04/24 68 */ 69/* 70 * Copyright (c) 1988 University of Utah. 71 * 72 * This code is derived from software contributed to Berkeley by 73 * the Systems Programming Group of the University of Utah Computer 74 * Science Department, The Mach Operating System project at 75 * Carnegie-Mellon University and Ralph Campbell. 76 * 77 * Redistribution and use in source and binary forms, with or without 78 * modification, are permitted provided that the following conditions 79 * are met: 80 * 1. Redistributions of source code must retain the above copyright 81 * notice, this list of conditions and the following disclaimer. 82 * 2. Redistributions in binary form must reproduce the above copyright 83 * notice, this list of conditions and the following disclaimer in the 84 * documentation and/or other materials provided with the distribution. 85 * 3. All advertising materials mentioning features or use of this software 86 * must display the following acknowledgement: 87 * This product includes software developed by the University of 88 * California, Berkeley and its contributors. 89 * 4. Neither the name of the University nor the names of its contributors 90 * may be used to endorse or promote products derived from this software 91 * without specific prior written permission. 92 * 93 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 94 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 95 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 96 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 97 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 98 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 99 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 101 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 102 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 103 * SUCH DAMAGE. 104 * 105 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 106 * from: Utah Hdr: machdep.c 1.63 91/04/24 107 */ 108 109#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 110__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.10 2009/02/13 22:41:01 apb Exp $"); 111 112#include "opt_ddb.h" 113#include "opt_kgdb.h" 114 115#include "opt_memsize.h" 116#include "opt_modular.h" 117#include "opt_ethaddr.h" 118 119#include "opt_pci.h" 120#include "pci.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/user.h> 128#include <sys/mount.h> 129#include <sys/kcore.h> 130#include <sys/boot_flag.h> 131#include <sys/termios.h> 132#include <sys/ksyms.h> 133#include <sys/device.h> 134 135#include <net/if.h> 136#include <net/if_ether.h> 137 138#include <uvm/uvm_extern.h> 139 140#include <dev/cons.h> 141 142#include "ksyms.h" 143 144#if NKSYMS || defined(DDB) || defined(MODULAR) 145#include <machine/db_machdep.h> 146#include <ddb/db_extern.h> 147#endif 148 149#include <mips/cache.h> 150#include <mips/locore.h> 151 152#include <mips/adm5120/include/adm5120reg.h> 153#include <mips/adm5120/include/adm5120var.h> 154#include <mips/adm5120/include/adm5120_extiovar.h> 155#include <mips/adm5120/include/adm5120_obiovar.h> 156#include <mips/adm5120/include/adm5120_mainbusvar.h> 157#include <mips/adm5120/include/adm5120_pcivar.h> 158#include <mips/adm5120/dev/uart.h> 159 160#ifndef MEMSIZE 161#define MEMSIZE 4 * 1024 * 1024 162#endif /* !MEMSIZE */ 163 164struct user *proc0paddr; 165 166/* Our exported CPU info; we can have only one. */ 167struct cpu_info cpu_info_store; 168 169/* Maps for VM objects. */ 170struct vm_map *mb_map = NULL; 171struct vm_map *phys_map = NULL; 172 173int physmem; /* # pages of physical memory */ 174int maxmem; /* max memory per process */ 175 176int mem_cluster_cnt; 177phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 178 179struct adm5120_config adm5120_configuration; 180 181void adm5120_setcpufreq(void); 182 183void 184adm5120_setcpufreq(void) 185{ 186 uint32_t v, freq; 187 188 v = SW_READ(SW_CODE_REG); 189 switch (v & CLKS_MASK) { 190 case CLKS_175MHZ: 191 freq = 175 * 1000 * 1000; 192 break; 193 case CLKS_200MHZ: 194 freq = 200 * 1000 * 1000; 195 break; 196 default: 197 panic("adm5120: cannot determine CPU clock speed"); 198 } 199 200 curcpu()->ci_cpu_freq = freq; 201 curcpu()->ci_cycles_per_hz = (freq + hz / 2) / hz / 2; 202 curcpu()->ci_divisor_delay = ((freq + 500000) / 1000000) / 2; 203} 204 205void mach_init(int, char **, void *, void *); /* XXX */ 206 207static void 208copy_args(int argc, char **argv) 209{ 210 struct adm5120_config *admc = &adm5120_configuration; 211 int i; 212 char *buf; 213 size_t buflen, rc; 214 215 buf = admc->args; 216 buflen = sizeof(admc->args); 217 218 if (argc >= __arraycount(admc->argv)) 219 panic("%s: too many boot args\n", __func__); 220 221 for (i = 0; buflen > 0 && i < argc && argv[i] != NULL; i++) { 222 admc->argv[i] = buf; 223 if ((rc = strlcpy(buf, argv[i], buflen)) >= buflen) 224 panic("%s: boot args too long\n", __func__); 225 226 buf += rc; 227 buflen -= rc; 228 *buf++ = '\0'; 229 buflen--; 230 } 231 if (i < argc) 232 panic("%s: boot args too long\n", __func__); 233 234 admc->argc = argc; 235} 236 237static void 238parse_args(prop_dictionary_t properties, int argc, char **argv, 239 uint32_t *memsizep) 240{ 241 char buf[32]; 242 char *key, *val, *valend; 243 unsigned long tmp; 244 int i; 245 uint8_t enaddr[ETHER_ADDR_LEN]; 246 247 if (memsizep != NULL) 248 *memsizep = MEMSIZE; 249 250 for (i = 0; i < argc && argv[i] != NULL; i++) { 251 if (strlcpy(buf, argv[i], sizeof(buf)) >= sizeof(buf)) 252 goto err; 253 val = buf; 254 key = strsep(&val, "="); 255 if (val == NULL) 256 goto err; 257 if (strcmp(key, "mem") == 0) { 258 tmp = strtoul(val, &valend, 10); 259 if (val == valend || *valend != 'M') 260 goto err; 261 if (memsizep != NULL) 262 *memsizep = tmp * 1024 * 1024; 263 } else if (strcmp(key, "HZ") == 0) 264 ; 265 else if (strcmp(key, "gpio") == 0) { 266 prop_number_t pn; 267 268 tmp = strtoul(val, &valend, 10); 269 if (val == valend || *valend != '\0') 270 goto err; 271 if (properties == NULL) 272 continue; 273 pn = prop_number_create_unsigned_integer(tmp); 274 if (pn == NULL) { 275 printf( 276 "%s: prop_number_create_unsigned_integer\n", 277 __func__); 278 continue; 279 } 280 if (!prop_dictionary_set(properties, "initial-gpio", 281 pn)) { 282 printf("%s: prop_dictionary_set(gpio)\n", 283 __func__); 284 } 285 prop_object_release(pn); 286 } else if (strcmp(key, "kmac") == 0) { 287 prop_data_t pd; 288 289 ether_nonstatic_aton(enaddr, val); 290 if (properties == NULL) 291 continue; 292 pd = prop_data_create_data(enaddr, sizeof(enaddr)); 293 if (pd == NULL) { 294 printf("%s: prop_data_create_data\n", __func__); 295 continue; 296 } 297 if (!prop_dictionary_set(properties, "mac-addr", pd)) { 298 printf("%s: prop_dictionary_set(mac)\n", 299 __func__); 300 } 301 prop_object_release(pd); 302 } else if (strcmp(key, "board") == 0) 303 printf("Routerboard %s\n", val); 304 else if (strcmp(key, "boot") == 0) 305 ; 306 continue; 307 err: 308 printf("bad argv[%d] (%s)\n", i, argv[i]); 309 } 310} 311 312void 313mach_init(int argc, char **argv, void *a2, void *a3) 314{ 315 struct adm5120_config *admc = &adm5120_configuration; 316 uint32_t memsize; 317 vaddr_t kernend; 318 u_long first, last; 319 vaddr_t v; 320 321 extern char edata[], end[]; /* XXX */ 322 323 /* clear the BSS segment */ 324 kernend = mips_round_page(end); 325 memset(edata, 0, kernend - (vaddr_t)edata); 326 327 /* set CPU model info for sysctl_hw */ 328 strcpy(cpu_model, "Infineon ADM5120"); 329 330 /* 331 * Set up the exception vectors and CPU-specific function 332 * vectors early on. We need the wbflush() vector set up 333 * before comcnattach() is called (or at least before the 334 * first printf() after that is called). 335 * Sets up mips_cpu_flags that may be queried by other 336 * functions called during startup. 337 * Also clears the I+D caches. 338 */ 339 mips_vector_init(); 340 341 /* 342 * Set the VM page size. 343 */ 344 uvm_setpagesize(); 345 346 adm5120_setcpufreq(); 347 348 /* 349 * Initialize bus space tags. 350 */ 351 obio_bus_mem_init(&admc->obio_space, admc); 352 extio_bus_mem_init(&admc->extio_space, admc); 353#if NPCI > 0 354 pciio_bus_mem_init(&admc->pciio_space, admc); 355 pcimem_bus_mem_init(&admc->pcimem_space, admc); 356#endif 357 358 /* 359 * Initialize bus DMA tag. 360 */ 361 obio_dma_init(&admc->obio_dmat); 362 363 /* 364 * Attach serial console. 365 */ 366 uart_cnattach(); 367 368 /* 369 * Look at arguments passed to us and compute boothowto. 370 */ 371 boothowto = RB_AUTOBOOT; 372#ifdef KADB 373 boothowto |= RB_KDB; 374#endif 375 376 parse_args(NULL, argc, argv, &memsize); 377 378 /* 379 * Determine the memory size. 380 * 381 * Note: Reserve the first page! That's where the trap 382 * vectors are located. 383 */ 384 385#if 0 386 if (GET_MEMSIZE(memsize) == 0) { 387 uint32_t val; 388 389 /* This does not seem to work... --dyoung */ 390 val = SW_READ(SW_MEMCONT_REG); 391 printf("SW_MEMCONT_REG: 0x%08" PRIx32 "\n", val); 392 switch (val & SDRAM_SIZE_MASK) { 393 case SDRAM_SIZE_4MBYTES: 394 memsize = 4 * 1024 * 1024; 395 break; 396 case SDRAM_SIZE_8MBYTES: 397 memsize = 8 * 1024 * 1024; 398 break; 399 case SDRAM_SIZE_16MBYTES: 400 memsize = 16 * 1024 * 1024; 401 break; 402 case SDRAM_SIZE_64MBYTES: 403 memsize = 64 * 1024 * 1024; 404 break; 405 case SDRAM_SIZE_128MBYTES: 406 memsize = 128 * 1024 * 1024; 407 break; 408 default: 409 panic("adm5120: cannot determine memory size"); 410 } 411 } 412#endif 413 414 physmem = btoc(memsize); 415 416 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 417 mem_clusters[mem_cluster_cnt].size = 418 memsize - mem_clusters[mem_cluster_cnt].start; 419 mem_cluster_cnt++; 420 421 /* 422 * Load the rest of the available pages into the VM system. 423 */ 424 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 425 last = mem_clusters[0].start + mem_clusters[0].size; 426 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 427 VM_FREELIST_DEFAULT); 428 429 /* 430 * Initialize message buffer (at end of core). 431 */ 432 mips_init_msgbuf(); 433 434 /* 435 * Initialize the virtual memory system. 436 */ 437 pmap_bootstrap(); 438 439 /* 440 * Init mapping for u page(s) for proc0. 441 */ 442 v = uvm_pageboot_alloc(USPACE); 443 lwp0.l_addr = proc0paddr = (struct user *)v; 444 lwp0.l_md.md_regs = (struct frame *)(v + USPACE) - 1; 445 proc0paddr->u_pcb.pcb_context[11] = 446 MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 447 448 /* 449 * Initialize debuggers, and break into them, if appropriate. 450 */ 451#ifdef DDB 452 if (boothowto & RB_KDB) 453 Debugger(); 454#endif 455 456 copy_args(argc, argv); 457} 458 459void 460consinit(void) 461{ 462 463 /* 464 * Everything related to console initialization is done 465 * in mach_init(). 466 */ 467} 468 469void 470cpu_startup(void) 471{ 472 struct adm5120_config *admc = &adm5120_configuration; 473 char pbuf[9]; 474 vaddr_t minaddr, maxaddr; 475#ifdef DEBUG 476 extern int pmapdebug; /* XXX */ 477 int opmapdebug = pmapdebug; 478 479 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 480#endif 481 482 if ((admc->properties = prop_dictionary_create()) == NULL) 483 printf("%s: prop_dictionary_create\n", __func__); 484 parse_args(admc->properties, admc->argc, admc->argv, NULL); 485 486 /* 487 * Good {morning,afternoon,evening,night}. 488 */ 489 printf("%s%s", copyright, version); 490 printf("%s\n", cpu_model); 491 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 492 printf("total memory = %s\n", pbuf); 493 494 minaddr = 0; 495 496 /* 497 * Allocate a submap for physio 498 */ 499 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 500 VM_PHYS_SIZE, 0, FALSE, NULL); 501 502 /* 503 * No need to allocate an mbuf cluster submap. Mbuf clusters 504 * are allocated via the pool allocator, and we use KSEG to 505 * map those pages. 506 */ 507 508#ifdef DEBUG 509 pmapdebug = opmapdebug; 510#endif 511 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 512 printf("avail memory = %s\n", pbuf); 513} 514 515void 516cpu_reboot(int howto, char *bootstr) 517{ 518 static int waittime = -1; 519 520 /* Take a snapshot before clobbering any registers. */ 521 if (curproc) 522 savectx((struct user *)curpcb); 523 524 /* If "always halt" was specified as a boot flag, obey. */ 525 if (boothowto & RB_HALT) 526 howto |= RB_HALT; 527 528 boothowto = howto; 529 530 /* If system is cold, just halt. */ 531 if (cold) { 532 boothowto |= RB_HALT; 533 goto haltsys; 534 } 535 536 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 537 waittime = 0; 538 539 /* 540 * Synchronize the disks.... 541 */ 542 vfs_shutdown(); 543 544 /* 545 * If we've been adjusting the clock, the todr 546 * will be out of synch; adjust it now. 547 */ 548 resettodr(); 549 } 550 551 /* Disable interrupts. */ 552 splhigh(); 553 554 if (boothowto & RB_DUMP) 555 dumpsys(); 556 557 haltsys: 558 /* Run any shutdown hooks. */ 559 doshutdownhooks(); 560 561 pmf_system_shutdown(boothowto); 562 563 /* 564 * Routerboard BIOS may autoboot, so "pseudo-halt". 565 */ 566 if (boothowto & RB_HALT) { 567 printf("\n"); 568 printf("The operating system has halted.\n"); 569 printf("Please press any key to reboot.\n\n"); 570 cnpollc(1); /* For proper keyboard command handling */ 571 cngetc(); 572 cnpollc(0); 573 } 574 575 printf("reseting board...\n\n"); 576 mips_icache_sync_all(); 577 mips_dcache_wbinv_all(); 578 SW_WRITE(SW_SFTRES_REG, 0); /* reset */ 579 for (;;) 580 /* spin forever */ ; /* XXX */ 581 /*NOTREACHED*/ 582} 583