1 /* $NetBSD: machdep.c,v 1.67 2002/03/17 04:41:57 tsutsui Exp $ */ 2 /* $OpenBSD: machdep.c,v 1.36 1999/05/22 21:22:19 weingart Exp $ */ 3 4 /* 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department, The Mach Operating System project at 12 * Carnegie-Mellon University and Ralph Campbell. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by the University of 25 * California, Berkeley and its contributors. 26 * 4. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * from: @(#)machdep.c 8.3 (Berkeley) 1/12/94 43 */ 44 45 /* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 46 47 #include "fs_mfs.h" 48 #include "opt_ddb.h" 49 #include "opt_md.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/signalvar.h> 54 #include <sys/kernel.h> 55 #include <sys/map.h> 56 #include <sys/proc.h> 57 #include <sys/buf.h> 58 #include <sys/reboot.h> 59 #include <sys/conf.h> 60 #include <sys/file.h> 61 #include <sys/malloc.h> 62 #include <sys/mbuf.h> 63 #include <sys/msgbuf.h> 64 #include <sys/ioctl.h> 65 #include <sys/time.h> 66 #include <sys/tty.h> 67 #include <sys/user.h> 68 #include <sys/exec.h> 69 #include <uvm/uvm_extern.h> 70 #include <sys/sysctl.h> 71 #include <sys/mount.h> 72 #include <sys/device.h> 73 #include <sys/syscallargs.h> 74 #include <sys/kcore.h> 75 #ifdef MFS 76 #include <ufs/mfs/mfs_extern.h> 77 #endif 78 79 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 80 81 #include <machine/cpu.h> 82 #include <machine/reg.h> 83 #include <machine/pio.h> 84 #include <machine/bus.h> 85 #include <machine/trap.h> 86 #include <machine/autoconf.h> 87 #include <machine/platform.h> 88 #include <mips/pte.h> 89 #include <mips/locore.h> 90 #include <mips/cpuregs.h> 91 #include <mips/psl.h> 92 #include <mips/cache.h> 93 #ifdef DDB 94 #include <mips/db_machdep.h> 95 #include <ddb/db_extern.h> 96 #endif 97 98 #include <dev/cons.h> 99 100 #include <dev/ic/i8042reg.h> 101 #include <dev/isa/isareg.h> 102 103 #include <arc/arc/arcbios.h> 104 #include <arc/arc/wired_map.h> 105 106 #include "com.h" 107 #if NCOM > 0 108 #include <sys/termios.h> 109 #include <dev/ic/comreg.h> 110 #include <dev/ic/comvar.h> 111 112 #ifndef COMCONSOLE 113 #define COMCONSOLE 0 114 #endif 115 116 #ifndef CONADDR 117 #define CONADDR 0 /* use default address if CONADDR isn't configured */ 118 #endif 119 120 #ifndef CONSPEED 121 #define CONSPEED TTYDEF_SPEED 122 #endif 123 #ifndef CONMODE 124 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 125 #endif 126 #endif /* NCOM */ 127 128 /* the following is used externally (sysctl_hw) */ 129 char machine[] = MACHINE; /* from <machine/param.h> */ 130 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 131 char cpu_model[80]; 132 133 /* Our exported CPU info; we can have only one. */ 134 struct cpu_info cpu_info_store; 135 136 /* maps for VM objects */ 137 struct vm_map *exec_map = NULL; 138 struct vm_map *mb_map = NULL; 139 struct vm_map *phys_map = NULL; 140 141 int maxmem; /* max memory per process */ 142 int physmem; /* max supported memory, changes to actual */ 143 int ncpu = 1; /* At least one cpu in the system */ 144 int cpuspeed = 150; /* approx CPU clock [MHz] */ 145 vaddr_t kseg2iobufsize = 0; /* to reserve PTEs for KSEG2 I/O space */ 146 struct arc_bus_space arc_bus_io;/* Bus tag for bus.h macros */ 147 struct arc_bus_space arc_bus_mem;/* Bus tag for bus.h macros */ 148 149 #if NCOM > 0 150 int com_freq = COM_FREQ; /* unusual clock frequency of dev/ic/com.c */ 151 int com_console = COMCONSOLE; 152 int com_console_address = CONADDR; 153 int com_console_speed = CONSPEED; 154 int com_console_mode = CONMODE; 155 #else 156 #ifndef COMCONSOLE 157 #error COMCONSOLE is defined without com driver configured. 158 #endif 159 int com_console = 0; 160 #endif /* NCOM */ 161 162 char **environment; /* On some arches, pointer to environment */ 163 164 int mem_reserved[VM_PHYSSEG_MAX]; /* the cluster is reserved, i.e. not free */ 165 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 166 int mem_cluster_cnt; 167 168 /* initialize bss, etc. from kernel start, before main() is called. */ 169 extern void mach_init __P((int, char **argv, char **)); 170 171 char *firmware_getenv __P((char *env)); 172 void arc_sysreset __P((bus_addr_t, bus_size_t)); 173 174 /* 175 * safepri is a safe priority for sleep to set for a spin-wait 176 * during autoconfiguration or after a panic. 177 * Used as an argument to splx(). 178 * XXX disables interrupt 5 to disable mips3 on-chip clock. 179 */ 180 int safepri = MIPS3_PSL_LOWIPL; 181 182 struct splvec splvec = { /* XXX will go XXX */ 183 MIPS_INT_MASK_SPLHIGH, /* splbio */ 184 MIPS_INT_MASK_SPLHIGH, /* splnet */ 185 MIPS_INT_MASK_SPLHIGH, /* spltty */ 186 MIPS_INT_MASK_SPLHIGH, /* splvm */ 187 MIPS_INT_MASK_SPLHIGH, /* splclock */ 188 MIPS_INT_MASK_SPLHIGH, /* splstatclock */ 189 }; 190 191 extern char kernel_text[], edata[], end[]; 192 extern struct user *proc0paddr; 193 194 /* 195 * Do all the stuff that locore normally does before calling main(). 196 * Process arguments passed to us by the BIOS. 197 * Reset mapping and set up mapping to hardware and init "wired" reg. 198 * Return the first page address following the system. 199 */ 200 void 201 mach_init(argc, argv, envv) 202 int argc; 203 char *argv[]; 204 char *envv[]; /* Not on all arches... */ 205 { 206 char *cp; 207 int i; 208 paddr_t kernstartpfn, kernendpfn, first, last; 209 caddr_t kernend, v; 210 vsize_t size; 211 212 /* clear the BSS segment in kernel code */ 213 kernend = (caddr_t)mips_round_page(end); 214 bzero(edata, kernend - edata); 215 216 environment = &argv[1]; 217 218 if (bios_ident()) { /* ARC BIOS present */ 219 bios_init_console(); 220 bios_save_info(); 221 physmem = bios_configure_memory(mem_reserved, mem_clusters, 222 &mem_cluster_cnt); 223 } 224 225 /* Initialize the CPU type */ 226 ident_platform(); 227 if (platform == NULL) { 228 /* This is probably the best we can do... */ 229 printf("kernel not configured for this system:\n"); 230 printf("ID [%s] Vendor [%8.8s] Product [%02x", 231 arc_id, arc_vendor_id, arc_product_id[0]); 232 for (i = 1; i < sizeof(arc_product_id); i++) 233 printf(":%02x", arc_product_id[i]); 234 printf("]\n"); 235 printf("DisplayController [%s]\n", arc_displayc_id); 236 #if 1 237 for (;;) 238 ; 239 #else 240 cpu_reboot(RB_HALT | RB_NOSYNC, NULL); 241 #endif 242 } 243 244 physmem = btoc(physmem); 245 246 /* compute bootdev for autoconfig setup */ 247 cp = firmware_getenv("OSLOADPARTITION"); 248 makebootdev(cp != NULL ? cp : argv[0]); 249 250 /* 251 * Look at arguments passed to us and compute boothowto. 252 * Default to SINGLE and ASKNAME if no args or 253 * SINGLE and DFLTROOT if this is a ramdisk kernel. 254 */ 255 #ifdef MEMORY_DISK_IS_ROOT 256 boothowto = RB_SINGLE; 257 #else 258 boothowto = RB_SINGLE | RB_ASKNAME; 259 #endif /* MEMORY_DISK_IS_ROOT */ 260 #ifdef KADB 261 boothowto |= RB_KDB; 262 #endif 263 264 cp = firmware_getenv("OSLOADOPTIONS"); 265 if (cp) { 266 while (*cp) { 267 switch (*cp++) { 268 case 'a': /* autoboot */ 269 boothowto &= ~RB_SINGLE; 270 break; 271 272 case 'm': /* mini root present in memory */ 273 boothowto |= RB_MINIROOT; 274 break; 275 276 case 'n': /* ask for names */ 277 boothowto |= RB_ASKNAME; 278 break; 279 280 case 'N': /* don't ask for names */ 281 boothowto &= ~RB_ASKNAME; 282 break; 283 284 case 's': /* use serial console */ 285 com_console = 1; 286 break; 287 288 case 'q': /* boot quietly */ 289 boothowto |= AB_QUIET; 290 break; 291 292 case 'v': /* boot verbosely */ 293 boothowto |= AB_VERBOSE; 294 break; 295 } 296 297 } 298 } 299 300 /* 301 * Set the VM page size. 302 */ 303 uvm_setpagesize(); 304 305 /* make sure that we don't call BIOS console from now on */ 306 cn_tab = NULL; 307 308 /* 309 * Copy exception-dispatch code down to exception vector. 310 * Initialize locore-function vector. 311 * Clear out the I and D caches. 312 * 313 * Now its time to abandon the BIOS and be self supplying. 314 * Start with cleaning out the TLB. Bye bye Microsoft.... 315 * 316 * This may clobber PTEs needed by the BIOS. 317 */ 318 mips_vector_init(); 319 320 /* 321 * Map critical I/O spaces (e.g. for console printf(9)) on KSEG2. 322 * We cannot call VM functions here, since uvm is not initialized, 323 * yet. 324 * Since printf(9) is called before uvm_init() in main(), 325 * we have to handcraft console I/O space anyway. 326 * 327 * XXX - reserve these KVA space after UVM initialization. 328 */ 329 330 arc_init_wired_map(); 331 332 (*platform->init)(); 333 cpuspeed = platform->clock; 334 sprintf(cpu_model, "%s %s%s", 335 platform->vendor, platform->model, platform->variant); 336 337 #ifdef MFS 338 /* 339 * Check to see if a mini-root was loaded into memory. It resides 340 * at the start of the next page just after the end of BSS. 341 */ 342 if (boothowto & RB_MINIROOT) 343 kernend += round_page(mfs_initminiroot(kernend)); 344 #endif 345 346 #ifdef DDB 347 #if 0 /* XXX */ 348 /* init symbols if present */ 349 if (esym) 350 ddb_init(1000, &end, (int*)esym); 351 #endif 352 #endif 353 354 maxmem = physmem; 355 356 /* XXX: revisit here */ 357 358 /* 359 * Load the rest of the pages into the VM system. 360 */ 361 kernstartpfn = atop(trunc_page( 362 MIPS_KSEG0_TO_PHYS((kernel_text) - UPAGES * PAGE_SIZE))); 363 kernendpfn = atop(round_page(MIPS_KSEG0_TO_PHYS(kernend))); 364 #if 0 365 /* give all free memory to VM */ 366 /* XXX - currently doesn't work, due to "panic: pmap_enter: pmap" */ 367 for (i = 0; i < mem_cluster_cnt; i++) { 368 if (mem_reserved[i]) 369 continue; 370 first = atop(round_page(mem_clusters[i].start)); 371 last = atop(trunc_page(mem_clusters[i].start + 372 mem_clusters[i].size)); 373 if (last <= kernstartpfn || kernendpfn <= first) { 374 uvm_page_physload(first, last, first, last, 375 VM_FREELIST_DEFAULT); 376 } else { 377 if (first < kernstartpfn) 378 uvm_page_physload(first, kernstartpfn, 379 first, kernstartpfn, VM_FREELIST_DEFAULT); 380 if (kernendpfn < last) 381 uvm_page_physload(kernendpfn, last, 382 kernendpfn, last, , VM_FREELIST_DEFAULT); 383 } 384 } 385 #elif 0 /* XXX */ 386 /* give all free memory above the kernel to VM (non-contig version) */ 387 for (i = 0; i < mem_cluster_cnt; i++) { 388 if (mem_reserved[i]) 389 continue; 390 first = atop(round_page(mem_clusters[i].start)); 391 last = atop(trunc_page(mem_clusters[i].start + 392 mem_clusters[i].size)); 393 if (kernendpfn < last) { 394 if (first < kernendpfn) 395 first = kernendpfn; 396 uvm_page_physload(first, last, first, last, 397 VM_FREELIST_DEFAULT); 398 } 399 } 400 #else 401 /* give all memory above the kernel to VM (contig version) */ 402 #if 1 403 mem_clusters[0].start = 0; 404 mem_clusters[0].size = ctob(physmem); 405 mem_cluster_cnt = 1; 406 #endif 407 408 first = kernendpfn; 409 last = physmem; 410 uvm_page_physload(first, last, first, last, VM_FREELIST_DEFAULT); 411 #endif 412 413 /* 414 * Initialize error message buffer (at end of core). 415 */ 416 mips_init_msgbuf(); 417 418 /* 419 * Compute the size of system data structures. pmap_bootstrap() 420 * needs some of this information. 421 */ 422 size = (vsize_t)allocsys(NULL, NULL); 423 424 /* 425 * Initialize the virtual memory system. 426 */ 427 pmap_bootstrap(); 428 429 /* 430 * Allocate space for proc0's USPACE. 431 */ 432 v = (caddr_t)uvm_pageboot_alloc(USPACE); 433 proc0.p_addr = proc0paddr = (struct user *)v; 434 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 435 curpcb = &proc0.p_addr->u_pcb; 436 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 437 438 /* 439 * Allocate space for system data structures. These data structures 440 * are allocated here instead of cpu_startup() because physical 441 * memory is directly addressable. We don't have to map these into 442 * virtual address space. 443 */ 444 v = (caddr_t)uvm_pageboot_alloc(size); 445 if ((allocsys(v, NULL) - v) != size) 446 panic("mach_init: table size inconsistency"); 447 } 448 449 void 450 mips_machdep_cache_config(void) 451 { 452 mips_sdcache_size = arc_cpu_l2cache_size; 453 } 454 455 /* 456 * Return a pointer to the given environment variable. 457 */ 458 char * 459 firmware_getenv(envname) 460 char *envname; 461 { 462 char **env; 463 int l; 464 465 l = strlen(envname); 466 467 for (env = environment; env[0]; env++) { 468 if (strncasecmp(envname, env[0], l) == 0 && env[0][l] == '=') { 469 return (&env[0][l + 1]); 470 } 471 } 472 return (NULL); 473 } 474 475 /* 476 * Console initialization: called early on from main, 477 * before vm init or startup. Do enough configuration 478 * to choose and initialize a console. 479 */ 480 void 481 consinit() 482 { 483 static int initted; 484 485 if (initted) 486 return; 487 initted = 1; 488 489 (*platform->cons_init)(); 490 } 491 492 /* 493 * cpu_startup: allocate memory for variable-sized tables, 494 * initialize cpu, and do autoconfiguration. 495 */ 496 void 497 cpu_startup() 498 { 499 unsigned i; 500 int base, residual; 501 vaddr_t minaddr, maxaddr; 502 vsize_t size; 503 char pbuf[9]; 504 #ifdef DEBUG 505 extern int pmapdebug; 506 int opmapdebug = pmapdebug; 507 508 pmapdebug = 0; /* Shut up pmap debug during bootstrap */ 509 #endif 510 511 /* 512 * Good {morning,afternoon,evening,night}. 513 */ 514 printf(version); 515 printf("%s\n", cpu_model); 516 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 517 printf("total memory = %s\n", pbuf); 518 519 /* 520 * Allocate virtual address space for file I/O buffers. 521 * Note they are different than the array of headers, 'buf', 522 * and usually occupy more virtual memory than physical. 523 */ 524 size = MAXBSIZE * nbuf; 525 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 526 NULL, UVM_UNKNOWN_OFFSET, 0, 527 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 528 UVM_ADV_NORMAL, 0)) != 0) 529 panic("cpu_startup: cannot allocate VM for buffers"); 530 531 minaddr = (vaddr_t)buffers; 532 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { 533 bufpages = btoc(MAXBSIZE) * nbuf; /* do not overallocate RAM */ 534 } 535 base = bufpages / nbuf; 536 residual = bufpages % nbuf; 537 538 /* now allocate RAM for buffers */ 539 for (i = 0; i < nbuf; i++) { 540 vsize_t curbufsize; 541 vaddr_t curbuf; 542 struct vm_page *pg; 543 544 /* 545 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 546 * that MAXBSIZE space, we allocate and map (base+1) pages 547 * for the first "residual" buffers, and then we allocate 548 * "base" pages for the rest. 549 */ 550 curbuf = (vaddr_t)buffers + (i * MAXBSIZE); 551 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 552 553 while (curbufsize) { 554 pg = uvm_pagealloc(NULL, 0, NULL, 0); 555 if (pg == NULL) 556 panic("cpu_startup: not enough memory for " 557 "buffer cache"); 558 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 559 VM_PROT_READ|VM_PROT_WRITE); 560 curbuf += PAGE_SIZE; 561 curbufsize -= PAGE_SIZE; 562 } 563 } 564 pmap_update(pmap_kernel()); 565 566 /* 567 * Allocate a submap for exec arguments. This map effectively 568 * limits the number of processes exec'ing at any time. 569 */ 570 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 571 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 572 573 /* 574 * Allocate a submap for physio 575 */ 576 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 577 VM_PHYS_SIZE, 0, FALSE, NULL); 578 579 /* 580 * No need to allocate an mbuf cluster submap. Mbuf clusters 581 * are allocated via the pool allocator, and we use KSEG to 582 * map those pages. 583 */ 584 585 #ifdef DEBUG 586 pmapdebug = opmapdebug; 587 #endif 588 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 589 printf("avail memory = %s\n", pbuf); 590 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 591 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 592 593 /* 594 * Set up buffers, so they can be used to read disk labels. 595 */ 596 bufinit(); 597 } 598 599 /* 600 * machine dependent system variables. 601 */ 602 int 603 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 604 int *name; 605 u_int namelen; 606 void *oldp; 607 size_t *oldlenp; 608 void *newp; 609 size_t newlen; 610 struct proc *p; 611 { 612 dev_t consdev; 613 614 /* all sysctl names at this level are terminal */ 615 if (namelen != 1) 616 return (ENOTDIR); /* overloaded */ 617 618 switch (name[0]) { 619 case CPU_CONSDEV: 620 if (cn_tab != NULL) 621 consdev = cn_tab->cn_dev; 622 else 623 consdev = NODEV; 624 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 625 sizeof consdev)); 626 default: 627 return (EOPNOTSUPP); 628 } 629 /* NOTREACHED */ 630 } 631 632 int waittime = -1; 633 struct user dumppcb; /* Actually, struct pcb would do. */ 634 635 void 636 cpu_reboot(howto, bootstr) 637 register int howto; 638 char *bootstr; 639 { 640 641 /* take a snap shot before clobbering any registers */ 642 if (curproc) 643 savectx((struct user *)curpcb); 644 645 #ifdef DEBUG 646 if (panicstr) 647 stacktrace(); 648 #endif 649 650 boothowto = howto; 651 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 652 /* fill curproc with live object */ 653 if (curproc == NULL) 654 curproc = &proc0; 655 /* 656 * Synchronize the disks.... 657 */ 658 waittime = 0; 659 vfs_shutdown(); 660 661 /* 662 * If we've been adjusting the clock, the todr 663 * will be out of synch; adjust it now. 664 */ 665 resettodr(); 666 } 667 (void) splhigh(); /* extreme priority */ 668 669 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 670 dumpsys(); 671 672 doshutdownhooks(); 673 674 if (howto & RB_HALT) { 675 printf("\n"); 676 printf("The operating system has halted.\n"); 677 printf("Please press any key to reboot.\n\n"); 678 cnpollc(1); /* for proper keyboard command handling */ 679 cngetc(); 680 cnpollc(0); 681 } 682 683 printf("rebooting...\n"); 684 delay(1000000); 685 686 (*platform->reset)(); 687 688 __asm__(" li $2, 0xbfc00000; jr $2; nop\n"); 689 for (;;) 690 ; /* Forever */ 691 /* NOTREACHED */ 692 } 693 694 /* 695 * Pass system reset command to keyboard controller (8042). 696 */ 697 void 698 arc_sysreset(addr, cmd_offset) 699 bus_addr_t addr; 700 bus_size_t cmd_offset; 701 { 702 volatile u_int8_t *kbdata = (u_int8_t *)addr + KBDATAP; 703 volatile u_int8_t *kbcmd = (u_int8_t *)addr + cmd_offset; 704 705 #define KBC_ARC_SYSRESET 0xd1 706 707 delay(1000); 708 *kbcmd = KBC_ARC_SYSRESET; 709 delay(1000); 710 *kbdata = 0; 711 } 712 713 /* 714 * Return the best possible estimate of the time in the timeval 715 * to which tvp points. Unfortunately, we can't read the hardware registers. 716 * We guarantee that the time will be greater than the value obtained by a 717 * previous call. 718 */ 719 void 720 microtime(tvp) 721 register struct timeval *tvp; 722 { 723 int s = splclock(); 724 static struct timeval lasttime; 725 726 *tvp = time; 727 #ifdef notdef 728 tvp->tv_usec += clkread(); 729 while (tvp->tv_usec >= 1000000) { 730 tvp->tv_sec++; 731 tvp->tv_usec -= 1000000; 732 } 733 #endif 734 if (tvp->tv_sec == lasttime.tv_sec && 735 tvp->tv_usec <= lasttime.tv_usec && 736 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 737 tvp->tv_sec++; 738 tvp->tv_usec -= 1000000; 739 } 740 lasttime = *tvp; 741 splx(s); 742 } 743