machdep.c revision 1.2
1/* $NetBSD: machdep.c,v 1.2 2007/05/17 14:51:17 yamt 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.2 2007/05/17 14:51:17 yamt Exp $"); 111 112#include "opt_ddb.h" 113#include "opt_kgdb.h" 114 115#include "opt_memsize.h" 116#include "opt_ethaddr.h" 117 118#include "opt_pci.h" 119#include "pci.h" 120 121#include <sys/param.h> 122#include <sys/systm.h> 123#include <sys/kernel.h> 124#include <sys/buf.h> 125#include <sys/reboot.h> 126#include <sys/user.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 133#include <net/if.h> 134#include <net/if_ether.h> 135 136#include <uvm/uvm_extern.h> 137 138#include <dev/cons.h> 139 140#include "ksyms.h" 141 142#if NKSYMS || defined(DDB) || defined(LKM) 143#include <machine/db_machdep.h> 144#include <ddb/db_extern.h> 145#endif 146 147#include <mips/cache.h> 148#include <mips/locore.h> 149 150#include <mips/adm5120/include/adm5120reg.h> 151#include <mips/adm5120/include/adm5120var.h> 152#include <mips/adm5120/include/adm5120_extiovar.h> 153#include <mips/adm5120/include/adm5120_obiovar.h> 154#include <mips/adm5120/include/adm5120_mainbusvar.h> 155#include <mips/adm5120/include/adm5120_pcivar.h> 156#include <mips/adm5120/dev/uart.h> 157 158#ifndef MEMSIZE 159#define MEMSIZE 4 * 1024 * 1024 160#endif /* !MEMSIZE */ 161 162struct user *proc0paddr; 163 164/* Our exported CPU info; we can have only one. */ 165struct cpu_info cpu_info_store; 166 167/* Maps for VM objects. */ 168struct vm_map *exec_map = NULL; 169struct vm_map *mb_map = NULL; 170struct vm_map *phys_map = NULL; 171 172int physmem; /* # pages of physical memory */ 173int maxmem; /* max memory per process */ 174 175int mem_cluster_cnt; 176phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 177 178struct adm5120_config adm5120_configuration; 179 180void adm5120_setcpufreq(void); 181 182void 183adm5120_setcpufreq(void) 184{ 185 uint32_t v, freq; 186 187 v = SW_READ(SW_CODE_REG); 188 switch (v & CLKS_MASK) { 189 case CLKS_175MHZ: 190 freq = 175 * 1000 * 1000; 191 break; 192 case CLKS_200MHZ: 193 freq = 200 * 1000 * 1000; 194 break; 195 default: 196 panic("adm5120: cannot determine CPU clock speed"); 197 } 198 199 curcpu()->ci_cpu_freq = freq; 200 curcpu()->ci_cycles_per_hz = (freq + hz / 2) / hz / 2; 201 curcpu()->ci_divisor_delay = ((freq + 500000) / 1000000) / 2; 202 MIPS_SET_CI_RECIPRICAL(curcpu()); 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#if NKSYMS || defined(DDB) || defined(LKM) 452 ksyms_init(0, 0, 0); 453#endif 454#ifdef DDB 455 if (boothowto & RB_KDB) 456 Debugger(); 457#endif 458 459 copy_args(argc, argv); 460} 461 462void 463consinit(void) 464{ 465 466 /* 467 * Everything related to console initialization is done 468 * in mach_init(). 469 */ 470} 471 472void 473cpu_startup(void) 474{ 475 struct adm5120_config *admc = &adm5120_configuration; 476 char pbuf[9]; 477 vaddr_t minaddr, maxaddr; 478#ifdef DEBUG 479 extern int pmapdebug; /* XXX */ 480 int opmapdebug = pmapdebug; 481 482 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 483#endif 484 485 if ((admc->properties = prop_dictionary_create()) == NULL) 486 printf("%s: prop_dictionary_create\n", __func__); 487 parse_args(admc->properties, admc->argc, admc->argv, NULL); 488 489 /* 490 * Good {morning,afternoon,evening,night}. 491 */ 492 printf("%s%s", copyright, version); 493 printf("%s\n", cpu_model); 494 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 495 printf("total memory = %s\n", pbuf); 496 497 minaddr = 0; 498 /* 499 * Allocate a submap for exec arguments. This map effectively 500 * limits the number of processes exec'ing at any time. 501 */ 502 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 503 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 504 505 /* 506 * Allocate a submap for physio 507 */ 508 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 509 VM_PHYS_SIZE, 0, FALSE, NULL); 510 511 /* 512 * No need to allocate an mbuf cluster submap. Mbuf clusters 513 * are allocated via the pool allocator, and we use KSEG to 514 * map those pages. 515 */ 516 517#ifdef DEBUG 518 pmapdebug = opmapdebug; 519#endif 520 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 521 printf("avail memory = %s\n", pbuf); 522} 523 524void 525cpu_reboot(int howto, char *bootstr) 526{ 527 static int waittime = -1; 528 529 /* Take a snapshot before clobbering any registers. */ 530 if (curproc) 531 savectx((struct user *)curpcb); 532 533 /* If "always halt" was specified as a boot flag, obey. */ 534 if (boothowto & RB_HALT) 535 howto |= RB_HALT; 536 537 boothowto = howto; 538 539 /* If system is cold, just halt. */ 540 if (cold) { 541 boothowto |= RB_HALT; 542 goto haltsys; 543 } 544 545 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 546 waittime = 0; 547 548 /* 549 * Synchronize the disks.... 550 */ 551 vfs_shutdown(); 552 553 /* 554 * If we've been adjusting the clock, the todr 555 * will be out of synch; adjust it now. 556 */ 557 resettodr(); 558 } 559 560 /* Disable interrupts. */ 561 splhigh(); 562 563 if (boothowto & RB_DUMP) 564 dumpsys(); 565 566 haltsys: 567 /* Run any shutdown hooks. */ 568 doshutdownhooks(); 569 570 /* 571 * Routerboard BIOS may autoboot, so "pseudo-halt". 572 */ 573 if (boothowto & RB_HALT) { 574 printf("\n"); 575 printf("The operating system has halted.\n"); 576 printf("Please press any key to reboot.\n\n"); 577 cnpollc(1); /* For proper keyboard command handling */ 578 cngetc(); 579 cnpollc(0); 580 } 581 582 printf("reseting board...\n\n"); 583 mips_icache_sync_all(); 584 mips_dcache_wbinv_all(); 585 SW_WRITE(SW_SFTRES_REG, 0); /* reset */ 586 for (;;) 587 /* spin forever */ ; /* XXX */ 588 /*NOTREACHED*/ 589} 590