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