machdep.c revision 1.23
1/* $NetBSD: machdep.c,v 1.23 2003/07/14 22:57:47 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 1988 University of Utah. 41 * Copyright (c) 1992, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * the Systems Programming Group of the University of Utah Computer 46 * Science Department, The Mach Operating System project at 47 * Carnegie-Mellon University and Ralph Campbell. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 3. All advertising materials mentioning features or use of this software 58 * must display the following acknowledgement: 59 * This product includes software developed by the University of 60 * California, Berkeley and its contributors. 61 * 4. Neither the name of the University nor the names of its contributors 62 * may be used to endorse or promote products derived from this software 63 * without specific prior written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 68 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 75 * SUCH DAMAGE. 76 * 77 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 78 * from: Utah Hdr: machdep.c 1.63 91/04/24 79 */ 80 81#include <sys/cdefs.h> 82__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.23 2003/07/14 22:57:47 lukem Exp $"); 83 84#include "opt_algor_p4032.h" 85#include "opt_algor_p5064.h" 86#include "opt_algor_p6032.h" 87 88#include "opt_ddb.h" 89#include "opt_kgdb.h" 90 91#include "opt_memsize.h" 92#include "opt_ethaddr.h" 93 94#include <sys/param.h> 95#include <sys/systm.h> 96#include <sys/kernel.h> 97#include <sys/buf.h> 98#include <sys/reboot.h> 99#include <sys/user.h> 100#include <sys/mount.h> 101#include <sys/kcore.h> 102#include <sys/boot_flag.h> 103#include <sys/termios.h> 104#include <sys/ksyms.h> 105 106#include <net/if.h> 107#include <net/if_ether.h> 108 109#include <uvm/uvm_extern.h> 110 111#include <dev/cons.h> 112 113#ifdef DDB 114#include <machine/db_machdep.h> 115#include <ddb/db_extern.h> 116#endif 117 118#include <machine/bus.h> 119#include <machine/autoconf.h> 120#include <machine/pmon.h> 121 122#include <algor/pci/vtpbcvar.h> 123 124#include "ksyms.h" 125 126#include "com.h" 127#if NCOM > 0 128#include <dev/ic/comreg.h> 129#include <dev/ic/comvar.h> 130 131int comcnrate = TTYDEF_SPEED; 132#endif /* NCOM > 0 */ 133 134#if defined(ALGOR_P4032) + \ 135 defined(ALGOR_P5064) + \ 136 defined(ALGOR_P6032) + \ 137 0 != 1 138#error Must configure exactly one platform. 139#endif 140 141#ifdef ALGOR_P4032 142#include <algor/algor/algor_p4032reg.h> 143#include <algor/algor/algor_p4032var.h> 144struct p4032_config p4032_configuration; 145#endif 146 147#ifdef ALGOR_P5064 148#include <algor/algor/algor_p5064reg.h> 149#include <algor/algor/algor_p5064var.h> 150struct p5064_config p5064_configuration; 151#endif 152 153#ifdef ALGOR_P6032 154#include <algor/algor/algor_p6032reg.h> 155#include <algor/algor/algor_p6032var.h> 156struct p6032_config p6032_configuration; 157#endif 158 159/* The following are used externally (sysctl_hw). */ 160extern char cpu_model[]; 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 178char algor_ethaddr[ETHER_ADDR_LEN]; 179 180void mach_init(int, char *[], char *[]); /* XXX */ 181 182int cpuspeed = 150; /* XXX XXX XXX */ 183 184void 185mach_init(int argc, char *argv[], char *envp[]) 186{ 187 extern char kernel_text[], edata[], end[]; 188 vaddr_t kernstart, kernend; 189 paddr_t kernstartpfn, kernendpfn, pfn0, pfn1; 190 vsize_t size; 191 const char *cp; 192 char *cp0; 193 caddr_t v; 194 int i; 195 196 /* Disable interrupts. */ 197 (void) splhigh(); 198 199 /* 200 * First, find the start and end of the kernel and clear 201 * the BSS segment. Account for a bit of space for the 202 * bootstrap stack. 203 */ 204 led_display('b', 's', 's', ' '); 205 kernstart = (vaddr_t) mips_trunc_page(kernel_text) - 2 * NBPG; 206 kernend = (vaddr_t) mips_round_page(end); 207 memset(edata, 0, kernend - (vaddr_t)edata); 208 209 /* 210 * Initialize PAGE_SIZE-dependent variables. 211 */ 212 led_display('p', 'g', 's', 'z'); 213 uvm_setpagesize(); 214 215 kernstartpfn = atop(MIPS_KSEG0_TO_PHYS(kernstart)); 216 kernendpfn = atop(MIPS_KSEG0_TO_PHYS(kernend)); 217 218 /* 219 * Initialize bus space tags and bring up the console. 220 */ 221#if defined(ALGOR_P4032) 222 { 223 struct p4032_config *acp = &p4032_configuration; 224 struct vtpbc_config *vt = &vtpbc_configuration; 225 bus_space_handle_t sh; 226 227 strcpy(cpu_model, "Algorithmics P-4032"); 228 229 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P4032_V962PBC); 230 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P4032_PCICFG); 231 vt->vt_adbase = 11; 232 233 led_display('v', '9', '6', '2'); 234 vtpbc_init(&acp->ac_pc, vt); 235 236 led_display('l', 'i', 'o', ' '); 237 algor_p4032loc_bus_io_init(&acp->ac_lociot, acp); 238 239 led_display('i', 'o', ' ', ' '); 240 algor_p4032_bus_io_init(&acp->ac_iot, acp); 241 242 led_display('m', 'e', 'm', ' '); 243 algor_p4032_bus_mem_init(&acp->ac_memt, acp); 244 245 led_display('d', 'm', 'a', ' '); 246 algor_p4032_dma_init(acp); 247#if NCOM > 0 248 /* 249 * Delay to allow firmware putchars to complete. 250 * FIFO depth * character time. 251 * character time = (1000000 / (defaultrate / 10)) 252 */ 253 led_display('c', 'o', 'n', 's'); 254 DELAY(160000000 / comcnrate); 255 if (comcnattach(&acp->ac_lociot, P4032_COM1, comcnrate, 256 COM_FREQ, COM_TYPE_NORMAL, 257 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 258 panic("p4032: unable to initialize serial console"); 259#else 260 panic("p4032: not configured to use serial console"); 261#endif /* NCOM > 0 */ 262 263 led_display('h', 'z', ' ', ' '); 264 bus_space_map(&acp->ac_lociot, P4032_RTC, 2, 0, &sh); 265 algor_p4032_cal_timer(&acp->ac_lociot, sh); 266 bus_space_unmap(&acp->ac_lociot, sh, 2); 267 } 268#elif defined(ALGOR_P5064) 269 { 270 struct p5064_config *acp = &p5064_configuration; 271 struct vtpbc_config *vt = &vtpbc_configuration; 272 bus_space_handle_t sh; 273 274 strcpy(cpu_model, "Algorithmics P-5064"); 275 276 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P5064_V360EPC); 277 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P5064_PCICFG); 278 vt->vt_adbase = 24; 279 280 led_display('v', '3', '6', '0'); 281 vtpbc_init(&acp->ac_pc, vt); 282 283 led_display('i', 'o', ' ', ' '); 284 algor_p5064_bus_io_init(&acp->ac_iot, acp); 285 286 led_display('m', 'e', 'm', ' '); 287 algor_p5064_bus_mem_init(&acp->ac_memt, acp); 288 289 led_display('d', 'm', 'a', ' '); 290 algor_p5064_dma_init(acp); 291#if NCOM > 0 292 /* 293 * Delay to allow firmware putchars to complete. 294 * FIFO depth * character time. 295 * character time = (1000000 / (defaultrate / 10)) 296 */ 297 led_display('c', 'o', 'n', 's'); 298 DELAY(160000000 / comcnrate); 299 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate, 300 COM_FREQ, COM_TYPE_NORMAL, 301 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 302 panic("p5064: unable to initialize serial console"); 303#else 304 panic("p5064: not configured to use serial console"); 305#endif /* NCOM > 0 */ 306 307 led_display('h', 'z', ' ', ' '); 308 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh); 309 algor_p5064_cal_timer(&acp->ac_iot, sh); 310 bus_space_unmap(&acp->ac_iot, sh, 2); 311 } 312#elif defined(ALGOR_P6032) 313 { 314 struct p6032_config *acp = &p6032_configuration; 315 struct bonito_config *bc = &acp->ac_bonito; 316 bus_space_handle_t sh; 317 318 strcpy(cpu_model, "Algorithmics P-6032"); 319 320 bc->bc_adbase = 11; 321 322 led_display('b','n','t','o'); 323 bonito_pci_init(&acp->ac_pc, bc); 324 325 led_display('i','o',' ',' '); 326 algor_p6032_bus_io_init(&acp->ac_iot, acp); 327 328 led_display('m','e','m',' '); 329 algor_p6032_bus_mem_init(&acp->ac_memt, acp); 330 331 led_display('d','m','a',' '); 332 algor_p6032_dma_init(acp); 333#if NCOM > 0 334 /* 335 * Delay to allow firmware putchars to complete. 336 * FIFO depth * character time. 337 * character time = (1000000 / (defaultrate / 10)) 338 */ 339 led_display('c','o','n','s'); 340 DELAY(160000000 / comcnrate); 341 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate, 342 COM_FREQ, COM_TYPE_NORMAL, 343 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 344 panic("p6032: unable to initialize serial console"); 345#else 346 panic("p6032: not configured to use serial console"); 347#endif /* NCOM > 0 */ 348 349 led_display('h','z',' ',' '); 350 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh); 351 algor_p6032_cal_timer(&acp->ac_iot, sh); 352 bus_space_unmap(&acp->ac_iot, sh, 2); 353 } 354#endif /* ALGOR_P4032 || ALGOR_P5064 || ALGOR_P6032 */ 355 356 /* 357 * The Algorithmics boards have PMON firmware; set up our 358 * PMON state. 359 */ 360 led_display('p', 'm', 'o', 'n'); 361 pmon_init(envp); 362 363 /* 364 * Get the Ethernet address of the on-board Ethernet. 365 */ 366#if defined(ETHADDR) 367 cp = ETHADDR; 368#else 369 cp = pmon_getenv("ethaddr"); 370#endif 371 if (cp != NULL) { 372 for (i = 0; i < ETHER_ADDR_LEN; i++) { 373 algor_ethaddr[i] = strtoul(cp, &cp0, 16); 374 cp = cp0 + 1; 375 } 376 } 377 378 /* 379 * Get the boot options. 380 */ 381 led_display('b', 'o', 'p', 't'); 382 boothowto = 0; 383 if (argc > 1) { 384 for (cp = argv[1]; cp != NULL && *cp != '\0'; cp++) { 385 switch (*cp) { 386#if defined(KGDB) || defined(DDB) 387 case 'd': /* break into kernel debugger */ 388 boothowto |= RB_KDB; 389 break; 390#endif 391 392 case 'h': /* always halt, never reboot */ 393 boothowto |= RB_HALT; 394 break; 395 396 case 'n': /* askname */ 397 boothowto |= RB_ASKNAME; 398 break; 399 400 case 's': /* single-user mode */ 401 boothowto |= RB_SINGLE; 402 break; 403 404 case 'q': /* quiet boot */ 405 boothowto |= AB_QUIET; 406 break; 407 408 case 'v': /* verbose boot */ 409 boothowto |= AB_VERBOSE; 410 break; 411 412 case '-': 413 /* 414 * Just ignore this. It's not required, 415 * but it's common for it to be passed 416 * regardless. 417 */ 418 break; 419 420 default: 421 printf("Unrecognized boto flag '%c'.\n", *cp); 422 break; 423 } 424 } 425 } 426 427 /* 428 * Determine the memory size. Use the `memsize' PMON 429 * variable. If that's not available, panic. 430 * 431 * Note: Reserve the first page! That's where the trap 432 * vectors are located. 433 */ 434#if defined(MEMSIZE) 435 size = MEMSIZE; 436#else 437 if ((cp = pmon_getenv("memsize")) != NULL) 438 size = strtoul(cp, NULL, 0); 439 else { 440 printf("FATAL: `memsize' PMON variable not set. Set it to\n"); 441 printf(" the amount of memory (in MB) and try again.\n"); 442 printf(" Or, build a kernel with the `MEMSIZE' " 443 "option.\n"); 444 panic("algor_init"); 445 } 446#endif /* MEMSIZE */ 447 /* 448 * Deal with 2 different conventions of the contents 449 * of the memsize variable -- if it's > 1024, assume 450 * it's already in bytes, not megabytes. 451 */ 452 if (size < 1024) { 453 printf("Memory size: 0x%08lx (0x%08lx)\n", size * 1024 * 1024, 454 size); 455 size *= 1024 * 1024; 456 } else 457 printf("Memory size: 0x%08lx\n", size); 458 459 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 460 mem_clusters[mem_cluster_cnt].size = 461 size - mem_clusters[mem_cluster_cnt].start; 462 mem_cluster_cnt++; 463 464 /* 465 * Copy the exception-dispatch code down to the exception vector. 466 * Initialize the locore function vector. Clear out the I- and 467 * D-caches. 468 * 469 * We can no longer call into PMON after this. 470 */ 471 led_display('v', 'e', 'c', 'i'); 472 mips_vector_init(); 473 474 /* 475 * Load the physical memory clusters into the VM system. 476 */ 477 led_display('v', 'm', 'p', 'g'); 478 for (i = 0; i < mem_cluster_cnt; i++) { 479 physmem += atop(mem_clusters[i].size); 480 pfn0 = atop(mem_clusters[i].start); 481 pfn1 = pfn0 + atop(mem_clusters[i].size); 482 if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) { 483 /* 484 * Must compute the location of the kernel 485 * within the segment. 486 */ 487#if 1 488 printf("Cluster %d contains kernel\n", i); 489#endif 490 if (pfn0 < kernstartpfn) { 491 /* 492 * There is a chunk before the kernel. 493 */ 494#if 1 495 printf("Loading chunk before kernel: " 496 "0x%lx / 0x%lx\n", pfn0, kernstartpfn); 497#endif 498 uvm_page_physload(pfn0, kernstartpfn, 499 pfn0, kernstartpfn, VM_FREELIST_DEFAULT); 500 } 501 if (kernendpfn < pfn1) { 502 /* 503 * There is a chunk after the kernel. 504 */ 505#if 1 506 printf("Loading chunk after kernel: " 507 "0x%lx / 0x%lx\n", kernendpfn, pfn1); 508#endif 509 uvm_page_physload(kernendpfn, pfn1, 510 kernendpfn, pfn1, VM_FREELIST_DEFAULT); 511 } 512 } else { 513 /* 514 * Just load this cluster as one chunk. 515 */ 516#if 1 517 printf("Loading cluster %d: 0x%lx / 0x%lx\n", i, 518 pfn0, pfn1); 519#endif 520 uvm_page_physload(pfn0, pfn1, pfn0, pfn1, 521 VM_FREELIST_DEFAULT); 522 } 523 } 524 525 if (physmem == 0) 526 panic("can't happen: system seems to have no memory!"); 527 maxmem = physmem; 528 529 /* 530 * Initialize message buffer (at end of core). 531 */ 532 mips_init_msgbuf(); 533 534 /* 535 * Compute the size of system data structures. pmap_bootstrap() 536 * needs some of this information. 537 */ 538 size = (vsize_t) allocsys(NULL, NULL); 539 540 /* 541 * Initialize the virtual memory system. 542 */ 543 led_display('p', 'm', 'a', 'p'); 544 pmap_bootstrap(); 545 546 /* 547 * Init mapping for u page(s) for lwp0. 548 */ 549 led_display('u', 's', 'p', 'c'); 550 v = (caddr_t) uvm_pageboot_alloc(USPACE); 551 lwp0.l_addr = proc0paddr = (struct user *) v; 552 lwp0.l_md.md_regs = (struct frame *)(v + USPACE) - 1; 553 curpcb = &lwp0.l_addr->u_pcb; 554 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 555 556 /* 557 * Allocate space for system data structures. These data structures 558 * are allocated here instead of cpu_startup() because physical 559 * memory is directly addressable. We don't have to map these into 560 * the virtual address space. 561 */ 562 v = (caddr_t) uvm_pageboot_alloc(size); 563 if ((allocsys(v, NULL) - v) != size) 564 panic("mach_init: table size inconsistency"); 565 566 /* 567 * Initialize debuggers, and break into them, if appropriate. 568 */ 569#if NKSYMS || defined(DDB) || defined(LKM) 570 /* 571 * XXX Loader doesn't give us symbols the way we like. Need 572 * XXX dbsym(1) support for ELF. 573 */ 574 ksyms_init(0, 0, 0); 575#endif 576 577 if (boothowto & RB_KDB) { 578#if defined(DDB) 579 Debugger(); 580#endif 581 } 582} 583 584void 585consinit(void) 586{ 587 588 /* 589 * Everything related to console initialization is done 590 * in mach_init(). 591 */ 592 led_display('N', 'B', 'S', 'D'); 593} 594 595void 596cpu_startup(void) 597{ 598 vsize_t size; 599 u_int i, base, residual; 600 vaddr_t minaddr, maxaddr; 601 char pbuf[9]; 602#ifdef DEBUG 603 extern int pmapdebug; 604 int opmapdebug = pmapdebug; 605 606 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 607#endif 608 609 /* 610 * Good {morning,afternoon,evening,night}. 611 */ 612 printf(version); 613 printf("%s\n", cpu_model); 614 format_bytes(pbuf, sizeof(pbuf), ptoa(physmem)); 615 printf("total memory = %s\n", pbuf); 616 617 /* 618 * Virtual memory is bootstrapped -- notify the bus spaces 619 * that memory allocation is now safe. 620 */ 621#if defined(ALGOR_P4032) 622 { 623 struct p4032_config *acp = &p4032_configuration; 624 625 acp->ac_mallocsafe = 1; 626 } 627#elif defined(ALGOR_P5064) 628 { 629 struct p5064_config *acp = &p5064_configuration; 630 631 acp->ac_mallocsafe = 1; 632 } 633#elif defined(ALGOR_P6032) 634 { 635 struct p6032_config *acp = &p6032_configuration; 636 637 acp->ac_mallocsafe = 1; 638 } 639#endif 640 641 /* 642 * Allocate virtual address space for file I/O buffers. 643 * Note they are different than the array of headers, 'buf', 644 * and usually occupy more virtual memory than physical. 645 */ 646 size = MAXBSIZE * nbuf; 647 if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), 648 NULL, UVM_UNKNOWN_OFFSET, 0, 649 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 650 UVM_ADV_NORMAL, 0)) != 0) 651 panic("cpu_startup: cannot allocate VM for buffers"); 652 base = bufpages / nbuf; 653 residual = bufpages % nbuf; 654 for (i = 0; i < nbuf; i++) { 655 vsize_t curbufsize; 656 vaddr_t curbuf; 657 struct vm_page *pg; 658 659 /* 660 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 661 * that MAXBSIZE space, we allocate and map (base+1) pages 662 * for the first "residual" buffers, and then we allocate 663 * "base" pages for the rest. 664 */ 665 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 666 curbufsize = PAGE_SIZE * ((i < residual) ? (base+1) : base); 667 668 while (curbufsize) { 669 pg = uvm_pagealloc(NULL, 0, NULL, 0); 670 if (pg == NULL) 671 panic("cpu_startup: not enough memory for " 672 "buffer cache"); 673 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 674 VM_PROT_READ|VM_PROT_WRITE); 675 curbuf += PAGE_SIZE; 676 curbufsize -= PAGE_SIZE; 677 } 678 } 679 pmap_update(pmap_kernel()); 680 681 /* 682 * Allocate a submap for exec arguments. This map effectively 683 * limits the number of processes exec'ing at any time. 684 */ 685 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 686 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 687 688 /* 689 * Allocate a submap for physio. 690 */ 691 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 692 VM_PHYS_SIZE, 0, FALSE, NULL); 693 694 /* 695 * No need to allocate an mbuf cluster submap. Mbuf clusters 696 * are allocate via the pool allocator, and we use KSEG0 to 697 * map those pages. 698 */ 699 700#ifdef DEBUG 701 pmapdebug = opmapdebug; 702#endif 703 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 704 printf("avail memory = %s\n", pbuf); 705 format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE); 706 printf("using %u buffers containing %s of memory\n", nbuf, pbuf); 707 708 /* 709 * Set up buffers, so they can be used to read disklabels. 710 */ 711 bufinit(); 712} 713 714int waittime = -1; 715struct user dumppcb; /* Actually, struct pcb would do. */ 716 717void 718cpu_reboot(int howto, char *bootstr) 719{ 720 int tmp; 721 722 /* Take a snapshot before clobbering any registers. */ 723 if (curlwp) 724 savectx((struct user *) curpcb); 725 726 /* If "always halt" was specified as a boot flag, obey. */ 727 if (boothowto & RB_HALT) 728 howto |= RB_HALT; 729 730 boothowto = howto; 731 732 /* If system is cold, just halt. */ 733 if (cold) { 734 boothowto |= RB_HALT; 735 goto haltsys; 736 } 737 738 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 739 waittime = 0; 740 vfs_shutdown(); 741 /* 742 * If we've been adjusting the clock, the todr 743 * will be out of synch; adjust it now. 744 */ 745 resettodr(); 746 } 747 748 /* Disable interrupts. */ 749 (void) splhigh(); 750 751 if (boothowto & RB_DUMP) 752 dumpsys(); 753 754 haltsys: 755 /* Run any shutdown hooks. */ 756 doshutdownhooks(); 757 758 if (boothowto & RB_HALT) { 759 printf("\n"); 760 printf("The operating system has halted.\n"); 761 printf("Please press any key to return to the monitor.\n\n"); 762 led_display('h','a','l','t'); 763 cnpollc(1); 764 (void) cngetc(); 765 cnpollc(0); 766 } 767 768 printf("Returning to the monitor...\n\n"); 769 led_display('r', 'v', 'e', 'c'); 770 /* Jump to the reset vector. */ 771 __asm __volatile("li %0, 0xbfc00000; jr %0; nop" 772 : "=r" (tmp) 773 : /* no inputs */ 774 : "memory"); 775 led_display('R', 'S', 'T', 'F'); 776 for (;;) 777 /* spin forever */ ; 778} 779 780/* 781 * XXX This shouldn't be here -- it should be done w/ devprops, 782 * XXX but we don't have those yet. 783 */ 784int 785algor_get_ethaddr(struct pci_attach_args *pa, u_int8_t *buf) 786{ 787 788#if defined(ALGOR_P4032) 789 if (pa->pa_bus != 0 || pa->pa_device != 5 || pa->pa_function != 0) 790 return (0); 791#elif defined(ALGOR_P5064) 792 if (pa->pa_bus != 0 || pa->pa_device != 0 || pa->pa_function != 0) 793 return (0); 794#elif defined(ALGOR_P6032) 795 if (pa->pa_bus != 0 || pa->pa_device != 16 || pa->pa_function != 0) 796 return (0); 797#endif 798 799 if (buf != NULL) 800 memcpy(buf, algor_ethaddr, sizeof(algor_ethaddr)); 801#if defined(ALGOR_P4032) 802 /* 803 * XXX This is gross, disgusting, and otherwise vile, but 804 * XXX V962 rev. < B2 have broken DMA FIFOs. Give the 805 * XXX on-board Ethernet a different DMA window that 806 * XXX has pre-fetching enabled so that Ethernet performance 807 * XXX doesn't completely suck. 808 */ 809 pa->pa_dmat = &p4032_configuration.ac_pci_pf_dmat; 810 pa->pa_dmat64 = NULL; 811#endif 812 return (1); 813} 814