1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department, The Mach Operating System project at 9 * Carnegie-Mellon University and Ralph Campbell. 10 * 11 * %sccs.include.redist.c% 12 * 13 * @(#)machdep.c 7.9 (Berkeley) 07/10/92 14 */ 15 16 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */ 17 18 #include "param.h" 19 #include "systm.h" 20 #include "signalvar.h" 21 #include "kernel.h" 22 #include "map.h" 23 #include "proc.h" 24 #include "buf.h" 25 #include "reboot.h" 26 #include "conf.h" 27 #include "file.h" 28 #include "clist.h" 29 #include "callout.h" 30 #include "malloc.h" 31 #include "mbuf.h" 32 #include "msgbuf.h" 33 #include "user.h" 34 #ifdef SYSVSHM 35 #include "shm.h" 36 #endif 37 38 #include "vm/vm.h" 39 #include "vm/vm_kern.h" 40 #include "vm/vm_page.h" 41 42 #include "../include/cpu.h" 43 #include "../include/reg.h" 44 #include "../include/psl.h" 45 #include "../include/machMon.h" 46 #include "../include/pte.h" 47 48 #include "../dev/device.h" 49 50 #include "clockreg.h" 51 52 vm_map_t buffer_map; 53 54 /* 55 * Declare these as initialized data so we can patch them. 56 */ 57 int nswbuf = 0; 58 #ifdef NBUF 59 int nbuf = NBUF; 60 #else 61 int nbuf = 0; 62 #endif 63 #ifdef BUFPAGES 64 int bufpages = BUFPAGES; 65 #else 66 int bufpages = 0; 67 #endif 68 int msgbufmapped; /* set when safe to use msgbuf */ 69 int maxmem; /* max memory per process */ 70 int physmem; /* max supported memory, changes to actual */ 71 /* 72 * safepri is a safe priority for sleep to set for a spin-wait 73 * during autoconfiguration or after a panic. 74 */ 75 int safepri = PSL_LOWIPL; 76 77 struct user *proc0paddr; 78 struct proc nullproc; /* for use by swtch_exit() */ 79 80 /* 81 * Do all the stuff that locore normally does before calling main(). 82 * Process arguments passed to us by the prom monitor. 83 * Return the first page address following the system. 84 */ 85 mach_init(argc, argv) 86 int argc; 87 char *argv[]; 88 { 89 register char *cp; 90 register int i; 91 register unsigned firstaddr; 92 register caddr_t v; 93 caddr_t start; 94 extern char edata[], end[]; 95 extern char MachUTLBMiss[], MachUTLBMissEnd[]; 96 extern char MachException[], MachExceptionEnd[]; 97 #ifdef ATTR 98 extern char *pmap_attributes; 99 #endif 100 101 /* clear the BSS segment */ 102 v = (caddr_t)pmax_round_page(end); 103 bzero(edata, v - edata); 104 105 #ifdef DS5000 106 /* check for direct boot from DS5000 PROM */ 107 if (argc > 0 && strcmp(argv[0], "boot") == 0) { 108 argc--; 109 argv++; 110 } 111 #endif 112 113 /* look at argv[0] and compute bootdev */ 114 makebootdev(argv[0]); 115 116 /* 117 * Look at arguments passed to us and compute boothowto. 118 */ 119 #ifdef GENERIC 120 boothowto = RB_SINGLE | RB_ASKNAME; 121 #else 122 boothowto = RB_SINGLE; 123 #endif 124 #ifdef KADB 125 boothowto |= RB_KDB; 126 #endif 127 if (argc > 1) { 128 for (i = 1; i < argc; i++) { 129 for (cp = argv[i]; *cp; cp++) { 130 switch (*cp) { 131 case 'a': /* autoboot */ 132 boothowto &= ~RB_SINGLE; 133 break; 134 135 case 'd': /* use compiled in default root */ 136 boothowto |= RB_DFLTROOT; 137 break; 138 139 case 'm': /* mini root present in memory */ 140 boothowto |= RB_MINIROOT; 141 break; 142 143 case 'n': /* ask for names */ 144 boothowto |= RB_ASKNAME; 145 break; 146 147 case 'N': /* don't ask for names */ 148 boothowto &= ~RB_ASKNAME; 149 } 150 } 151 } 152 } 153 154 #ifdef MFS 155 /* 156 * Check to see if a mini-root was loaded into memory. It resides 157 * at the start of the next page just after the end of BSS. 158 */ 159 if (boothowto & RB_MINIROOT) 160 v += mfs_initminiroot(v); 161 #endif 162 163 /* 164 * Init mapping for u page(s) for proc[0], pm_tlbpid 1. 165 */ 166 start = v; 167 curproc->p_addr = proc0paddr = (struct user *)v; 168 curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs; 169 firstaddr = MACH_CACHED_TO_PHYS(v); 170 for (i = 0; i < UPAGES; i++) { 171 MachTLBWriteIndexed(i, 172 (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT), 173 curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M); 174 firstaddr += NBPG; 175 } 176 v += UPAGES * NBPG; 177 MachSetPID(1); 178 179 /* 180 * init nullproc for swtch_exit(). 181 * init mapping for u page(s), pm_tlbpid 0 182 * This could be used for an idle process. 183 */ 184 nullproc.p_addr = (struct user *)v; 185 nullproc.p_md.md_regs = ((struct user *)v)->u_pcb.pcb_regs; 186 for (i = 0; i < UPAGES; i++) { 187 nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M; 188 firstaddr += NBPG; 189 } 190 v += UPAGES * NBPG; 191 192 /* clear pages for u areas */ 193 bzero(start, v - start); 194 195 /* 196 * Copy down exception vector code. 197 */ 198 if (MachUTLBMissEnd - MachUTLBMiss > 0x80) 199 panic("startup: UTLB code too large"); 200 bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC, 201 MachUTLBMissEnd - MachUTLBMiss); 202 bcopy(MachException, (char *)MACH_GEN_EXC_VEC, 203 MachExceptionEnd - MachException); 204 205 /* 206 * Clear out the I and D caches. 207 */ 208 MachConfigCache(); 209 MachFlushCache(); 210 211 /* 212 * Determine what model of computer we are running on. 213 */ 214 { 215 char *(*f)() = (char *(*)())MACH_MON_GETENV2; 216 217 if (cp = (*f)("systype")) 218 i = atoi(cp); 219 else 220 cp = ""; 221 222 /* check for MIPS based platform */ 223 if (((i >> 24) & 0xFF) != 0x82) { 224 printf("Unknown System type '%s'\n", cp); 225 boot(RB_HALT | RB_NOSYNC); 226 } 227 } 228 229 /* check what model platform we are running on */ 230 switch ((i >> 16) & 0xFF) { 231 #ifdef DS3100 232 case 1: /* DS3100 Pmax */ 233 /* 234 * Find out how much memory is available. 235 */ 236 physmem = btoc(v - KERNBASE); 237 cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT); 238 while (cp < (char *)MACH_MAX_MEM_ADDR) { 239 if (badaddr(cp, 4)) 240 break; 241 cp += NBPG; 242 physmem++; 243 } 244 break; 245 #endif 246 247 #ifdef DS5000 248 case 2: /* DS5000 3max */ 249 { 250 extern void tc_find_all_options(); 251 252 /* disable all TURBOchannel interrupts */ 253 i = *(volatile int *)MACH_SYS_CSR_ADDR; 254 *(volatile int *)MACH_SYS_CSR_ADDR = i & ~(MACH_CSR_MBZ | 0xFF); 255 256 /* 257 * Probe the TURBOchannel to see what controllers are present. 258 */ 259 tc_find_all_options(); 260 261 /* clear any memory errors from probes */ 262 *(unsigned *)MACH_ERROR_ADDR = 0; 263 264 /* 265 * Find out how much memory is available. 266 */ 267 physmem = btoc(v - KERNBASE); 268 cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT); 269 while (cp < (char *)MACH_MAX_MEM_ADDR) { 270 if (badaddr(cp, 4)) 271 break; 272 *(int *)cp = 0xa5a5a5a5; 273 /* 274 * Data will persist on the bus if we read it right 275 * away. Have to be tricky here. 276 */ 277 ((int *)cp)[4] = 0x5a5a5a5a; 278 MachEmptyWriteBuffer(); 279 if (*(int *)cp != 0xa5a5a5a5) 280 break; 281 cp += NBPG; 282 physmem++; 283 } 284 break; 285 } 286 #endif DS5000 287 288 case 5: /* DS5800 Isis */ 289 case 6: /* DS5400 MIPSfair */ 290 default: 291 printf("kernel not configured for systype 0x%x\n", i); 292 boot(RB_HALT | RB_NOSYNC); 293 } 294 295 maxmem = physmem; 296 297 /* 298 * Initialize error message buffer (at end of core). 299 */ 300 maxmem -= btoc(sizeof (struct msgbuf)); 301 msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT)); 302 msgbufmapped = 1; 303 304 /* 305 * Allocate space for system data structures. 306 * The first available kernel virtual address is in "v". 307 * As pages of kernel virtual memory are allocated, "v" is incremented. 308 * 309 * These data structures are allocated here instead of cpu_startup() 310 * because physical memory is directly addressable. We don't have 311 * to map these into virtual address space. 312 */ 313 start = v; 314 315 #define valloc(name, type, num) \ 316 (name) = (type *)v; v = (caddr_t)((name)+(num)) 317 #define valloclim(name, type, num, lim) \ 318 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 319 valloc(cfree, struct cblock, nclist); 320 valloc(callout, struct callout, ncallout); 321 valloc(swapmap, struct map, nswapmap = maxproc * 2); 322 #ifdef SYSVSHM 323 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 324 #endif 325 #ifdef ATTR 326 /* this is allocated here just to save a few bytes */ 327 valloc(pmap_attributes, char, physmem); 328 #endif 329 330 /* 331 * Determine how many buffers to allocate. 332 * We allocate more buffer space than the BSD standard of 333 * using 10% of memory for the first 2 Meg, 5% of remaining. 334 * We just allocate a flat 10%. Insure a minimum of 16 buffers. 335 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 336 */ 337 if (bufpages == 0) 338 bufpages = physmem / 10 / CLSIZE; 339 if (nbuf == 0) { 340 nbuf = bufpages; 341 if (nbuf < 16) 342 nbuf = 16; 343 } 344 if (nswbuf == 0) { 345 nswbuf = (nbuf / 2) &~ 1; /* force even */ 346 if (nswbuf > 256) 347 nswbuf = 256; /* sanity */ 348 } 349 valloc(swbuf, struct buf, nswbuf); 350 valloc(buf, struct buf, nbuf); 351 352 /* 353 * Clear allocated memory. 354 */ 355 v = (caddr_t)pmax_round_page(v); 356 bzero(start, v - start); 357 358 /* 359 * Initialize the virtual memory system. 360 */ 361 pmap_bootstrap((vm_offset_t)MACH_CACHED_TO_PHYS(v)); 362 } 363 364 /* 365 * Console initialization: called early on from main, 366 * before vm init or startup. Do enough configuration 367 * to choose and initialize a console. 368 * XXX need something better here. 369 */ 370 consinit() 371 { 372 373 #include "pm.h" 374 #if NPM > 0 375 if (pminit()) 376 return; 377 #endif 378 379 #include "cfb.h" 380 #if NCFB > 0 381 { 382 register struct pmax_ctlr *cp; 383 register struct driver *drp; 384 385 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) { 386 if (strcmp(drp->d_name, "cfb")) 387 continue; 388 if (cfb_init(cp)) 389 return; 390 } 391 } 392 #endif 393 } 394 395 /* 396 * cpu_startup: allocate memory for variable-sized tables, 397 * initialize cpu, and do autoconfiguration. 398 */ 399 cpu_startup() 400 { 401 register unsigned i; 402 register caddr_t v; 403 int base, residual; 404 extern long Usrptsize; 405 extern struct map *useriomap; 406 #ifdef DEBUG 407 extern int pmapdebug; 408 int opmapdebug = pmapdebug; 409 #endif 410 vm_offset_t minaddr, maxaddr; 411 vm_size_t size; 412 413 #ifdef DEBUG 414 pmapdebug = 0; 415 #endif 416 417 /* 418 * Good {morning,afternoon,evening,night}. 419 */ 420 printf(version); 421 printf("real mem = %d\n", ctob(physmem)); 422 423 /* 424 * Allocate virtual address space for file I/O buffers. 425 * Note they are different than the array of headers, 'buf', 426 * and usually occupy more virtual memory than physical. 427 */ 428 size = MAXBSIZE * nbuf; 429 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 430 &maxaddr, size, FALSE); 431 minaddr = (vm_offset_t)buffers; 432 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 433 &minaddr, size, FALSE) != KERN_SUCCESS) 434 panic("startup: cannot allocate buffers"); 435 base = bufpages / nbuf; 436 residual = bufpages % nbuf; 437 for (i = 0; i < nbuf; i++) { 438 vm_size_t curbufsize; 439 vm_offset_t curbuf; 440 441 /* 442 * First <residual> buffers get (base+1) physical pages 443 * allocated for them. The rest get (base) physical pages. 444 * 445 * The rest of each buffer occupies virtual space, 446 * but has no physical memory allocated for it. 447 */ 448 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 449 curbufsize = CLBYTES * (i < residual ? base+1 : base); 450 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 451 vm_map_simplify(buffer_map, curbuf); 452 } 453 /* 454 * Allocate a submap for exec arguments. This map effectively 455 * limits the number of processes exec'ing at any time. 456 */ 457 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 458 16*NCARGS, TRUE); 459 /* 460 * Allocate a submap for physio 461 */ 462 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 463 VM_PHYS_SIZE, TRUE); 464 465 /* 466 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 467 * we use the more space efficient malloc in place of kmem_alloc. 468 */ 469 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 470 M_MBUF, M_NOWAIT); 471 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 472 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 473 VM_MBUF_SIZE, FALSE); 474 /* 475 * Initialize callouts 476 */ 477 callfree = callout; 478 for (i = 1; i < ncallout; i++) 479 callout[i-1].c_next = &callout[i]; 480 callout[i-1].c_next = NULL; 481 482 #ifdef DEBUG 483 pmapdebug = opmapdebug; 484 #endif 485 printf("avail mem = %d\n", ptoa(cnt.v_free_count)); 486 printf("using %d buffers containing %d bytes of memory\n", 487 nbuf, bufpages * CLBYTES); 488 /* 489 * Set up CPU-specific registers, cache, etc. 490 */ 491 initcpu(); 492 493 /* 494 * Set up buffers, so they can be used to read disk labels. 495 */ 496 bufinit(); 497 498 /* 499 * Configure the system. 500 */ 501 configure(); 502 } 503 504 /* 505 * Set registers on exec. 506 * Clear all registers except sp, pc. 507 */ 508 setregs(p, entry, retval) 509 register struct proc *p; 510 u_long entry; 511 int retval[2]; 512 { 513 int sp = p->p_md.md_regs[SP]; 514 extern struct proc *machFPCurProcPtr; 515 516 bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int)); 517 p->p_md.md_regs[SP] = sp; 518 p->p_md.md_regs[PC] = entry; 519 p->p_md.md_regs[PS] = PSL_USERSET; 520 p->p_md.md_flags & ~MDP_FPUSED; 521 if (machFPCurProcPtr == p) 522 machFPCurProcPtr = (struct proc *)0; 523 } 524 525 /* 526 * WARNING: code in locore.s assumes the layout shown for sf_signum 527 * thru sf_handler so... don't screw with them! 528 */ 529 struct sigframe { 530 int sf_signum; /* signo for handler */ 531 int sf_code; /* additional info for handler */ 532 struct sigcontext *sf_scp; /* context ptr for handler */ 533 sig_t sf_handler; /* handler addr for u_sigc */ 534 }; 535 536 #ifdef DEBUG 537 int sigdebug = 0; 538 int sigpid = 0; 539 #define SDB_FOLLOW 0x01 540 #define SDB_KSTACK 0x02 541 #define SDB_FPSTATE 0x04 542 #endif 543 544 /* 545 * Send an interrupt to process. 546 */ 547 void 548 sendsig(catcher, sig, mask, code) 549 sig_t catcher; 550 int sig, mask; 551 unsigned code; 552 { 553 register struct proc *p = curproc; 554 register struct sigframe *fp; 555 register struct sigacts *psp = p->p_sigacts; 556 register struct sigcontext *scp; 557 register int *regs; 558 int oonstack, fsize; 559 struct sigcontext ksc; 560 561 regs = p->p_md.md_regs; 562 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 563 /* 564 * Allocate and validate space for the signal handler 565 * context. Note that if the stack is in data space, the 566 * call to grow() is a nop, and the copyout() 567 * will fail if the process has not already allocated 568 * the space with a `brk'. 569 */ 570 if ((psp->ps_flags & SAS_ALTSTACK) && 571 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 572 (psp->ps_sigonstack & sigmask(sig))) { 573 scp = (struct sigcontext *)(psp->ps_sigstk.ss_base + 574 psp->ps_sigstk.ss_size) - 1; 575 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 576 } else 577 scp = (struct sigcontext *)regs[SP] - 1; 578 fp = (struct sigframe *)scp - 1; 579 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 580 (void)grow(p, (unsigned)fp); 581 /* 582 * Build the signal context to be used by sigreturn. 583 */ 584 ksc.sc_onstack = oonstack; 585 ksc.sc_mask = mask; 586 ksc.sc_pc = regs[PC]; 587 ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ 588 bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1], 589 sizeof(ksc.sc_regs) - sizeof(int)); 590 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 591 if (ksc.sc_fpused) { 592 extern struct proc *machFPCurProcPtr; 593 594 /* if FPU has current state, save it first */ 595 if (p == machFPCurProcPtr) 596 MachSaveCurFPState(p); 597 bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs, 598 sizeof(ksc.sc_fpregs)); 599 } 600 if (copyout((caddr_t)&ksc, (caddr_t)scp, sizeof(ksc))) { 601 /* 602 * Process has trashed its stack; give it an illegal 603 * instruction to halt it in its tracks. 604 */ 605 SIGACTION(p, SIGILL) = SIG_DFL; 606 sig = sigmask(SIGILL); 607 p->p_sigignore &= ~sig; 608 p->p_sigcatch &= ~sig; 609 p->p_sigmask &= ~sig; 610 psignal(p, SIGILL); 611 return; 612 } 613 /* 614 * Build the argument list for the signal handler. 615 */ 616 regs[A0] = sig; 617 regs[A1] = code; 618 regs[A2] = (int)scp; 619 regs[A3] = (int)catcher; 620 621 regs[PC] = (int)catcher; 622 regs[SP] = (int)fp; 623 regs[RA] = KERNBASE; /* this causes a trap which we interpret as 624 * meaning "do a sigreturn". */ 625 #ifdef DEBUG 626 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 627 printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", 628 p->p_pid, sig, &oonstack, fp, fp->sf_scp); 629 #endif 630 } 631 632 /* 633 * System call to cleanup state after a signal 634 * has been taken. Reset signal mask and 635 * stack state from context left by sendsig (above). 636 * Return to previous pc and psl as specified by 637 * context left by sendsig. Check carefully to 638 * make sure that the user has not modified the 639 * psl to gain improper priviledges or to cause 640 * a machine fault. 641 */ 642 struct sigreturn_args { 643 struct sigcontext *sigcntxp; 644 }; 645 /* ARGSUSED */ 646 sigreturn(p, uap, retval) 647 struct proc *p; 648 struct sigreturn_args *uap; 649 int *retval; 650 { 651 register struct sigcontext *scp; 652 register int *regs; 653 struct sigcontext ksc; 654 int error; 655 656 register struct frame *frame; 657 register int rf; 658 struct sigcontext tsigc; 659 int flags; 660 661 scp = uap->sigcntxp; 662 #ifdef DEBUG 663 if (sigdebug & SDB_FOLLOW) 664 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 665 #endif 666 regs = p->p_md.md_regs; 667 /* 668 * Test and fetch the context structure. 669 * We grab it all at once for speed. 670 */ 671 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); 672 if (error != 0 || ksc.sc_regs[ZERO] != 0xACEDBADE || 673 (unsigned)ksc.sc_regs[SP] < (unsigned)regs[SP]) { 674 #ifdef DEBUG 675 if (!(sigdebug & SDB_FOLLOW)) 676 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 677 printf(" old sp %x ra %x pc %x\n", 678 regs[SP], regs[RA], regs[PC]); 679 printf(" new sp %x ra %x pc %x err %d z %x\n", 680 ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], 681 error, ksc.sc_regs[ZERO]); 682 #endif 683 if (regs[PC] == KERNBASE) { 684 int sig; 685 686 /* 687 * Process has trashed its stack; give it an illegal 688 * instruction to halt it in its tracks. 689 */ 690 SIGACTION(p, SIGILL) = SIG_DFL; 691 sig = sigmask(SIGILL); 692 p->p_sigignore &= ~sig; 693 p->p_sigcatch &= ~sig; 694 p->p_sigmask &= ~sig; 695 psignal(p, SIGILL); 696 } 697 return (EINVAL); 698 } 699 /* 700 * Restore the user supplied information 701 */ 702 if (scp->sc_onstack & 01) 703 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 704 else 705 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 706 p->p_sigmask = scp->sc_mask &~ sigcantmask; 707 regs[PC] = ksc.sc_pc; 708 bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)®s[1], 709 sizeof(ksc.sc_regs) - sizeof(int)); 710 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 711 if (ksc.sc_fpused) 712 bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_md.md_regs[F0], 713 sizeof(ksc.sc_fpregs)); 714 return (EJUSTRETURN); 715 } 716 717 int waittime = -1; 718 719 boot(howto) 720 register int howto; 721 { 722 723 /* take a snap shot before clobbering any registers */ 724 if (curproc) 725 savectx(curproc->p_addr, 0); 726 727 howto |= RB_HALT; /* XXX */ 728 boothowto = howto; 729 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 730 register struct buf *bp; 731 int iter, nbusy; 732 733 waittime = 0; 734 (void) spl0(); 735 printf("syncing disks... "); 736 /* 737 * Release vnodes held by texts before sync. 738 */ 739 if (panicstr == 0) 740 vnode_pager_umount(NULL); 741 #ifdef notdef 742 #include "fd.h" 743 #if NFD > 0 744 fdshutdown(); 745 #endif 746 #endif 747 sync(&proc0, (void *)NULL, (int *)NULL); 748 749 for (iter = 0; iter < 20; iter++) { 750 nbusy = 0; 751 for (bp = &buf[nbuf]; --bp >= buf; ) 752 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 753 nbusy++; 754 if (nbusy == 0) 755 break; 756 printf("%d ", nbusy); 757 DELAY(40000 * iter); 758 } 759 if (nbusy) 760 printf("giving up\n"); 761 else 762 printf("done\n"); 763 /* 764 * If we've been adjusting the clock, the todr 765 * will be out of synch; adjust it now. 766 */ 767 resettodr(); 768 } 769 (void) splhigh(); /* extreme priority */ 770 if (howto & RB_HALT) { 771 void (*f)() = (void (*)())MACH_MON_REINIT; 772 773 (*f)(); /* jump back to prom monitor */ 774 } else { 775 void (*f)() = (void (*)())MACH_MON_AUTOBOOT; 776 777 if (howto & RB_DUMP) 778 dumpsys(); 779 (*f)(); /* jump back to prom monitor and do 'auto' cmd */ 780 /*NOTREACHED*/ 781 } 782 /*NOTREACHED*/ 783 } 784 785 int dumpmag = 0x8fca0101; /* magic number for savecore */ 786 int dumpsize = 0; /* also for savecore */ 787 long dumplo = 0; 788 789 dumpconf() 790 { 791 int nblks; 792 793 dumpsize = physmem; 794 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 795 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 796 if (dumpsize > btoc(dbtob(nblks - dumplo))) 797 dumpsize = btoc(dbtob(nblks - dumplo)); 798 else if (dumplo == 0) 799 dumplo = nblks - btodb(ctob(physmem)); 800 } 801 /* 802 * Don't dump on the first CLBYTES (why CLBYTES?) 803 * in case the dump device includes a disk label. 804 */ 805 if (dumplo < btodb(CLBYTES)) 806 dumplo = btodb(CLBYTES); 807 } 808 809 /* 810 * Doadump comes here after turning off memory management and 811 * getting on the dump stack, either when called above, or by 812 * the auto-restart code. 813 */ 814 dumpsys() 815 { 816 int error; 817 818 msgbufmapped = 0; 819 if (dumpdev == NODEV) 820 return; 821 /* 822 * For dumps during autoconfiguration, 823 * if dump device has already configured... 824 */ 825 if (dumpsize == 0) 826 dumpconf(); 827 if (dumplo < 0) 828 return; 829 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 830 printf("dump "); 831 switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 832 833 case ENXIO: 834 printf("device bad\n"); 835 break; 836 837 case EFAULT: 838 printf("device not ready\n"); 839 break; 840 841 case EINVAL: 842 printf("area improper\n"); 843 break; 844 845 case EIO: 846 printf("i/o error\n"); 847 break; 848 849 default: 850 printf("error %d\n", error); 851 break; 852 853 case 0: 854 printf("succeeded\n"); 855 } 856 } 857 858 /* 859 * Return the best possible estimate of the time in the timeval 860 * to which tvp points. Unfortunately, we can't read the hardware registers. 861 * We guarantee that the time will be greater than the value obtained by a 862 * previous call. 863 */ 864 microtime(tvp) 865 register struct timeval *tvp; 866 { 867 int s = splclock(); 868 static struct timeval lasttime; 869 870 *tvp = time; 871 #ifdef notdef 872 tvp->tv_usec += clkread(); 873 while (tvp->tv_usec > 1000000) { 874 tvp->tv_sec++; 875 tvp->tv_usec -= 1000000; 876 } 877 #endif 878 if (tvp->tv_sec == lasttime.tv_sec && 879 tvp->tv_usec <= lasttime.tv_usec && 880 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 881 tvp->tv_sec++; 882 tvp->tv_usec -= 1000000; 883 } 884 lasttime = *tvp; 885 splx(s); 886 } 887 888 initcpu() 889 { 890 register volatile struct chiptime *c; 891 int i; 892 893 /* disable clock interrupts (until startrtclock()) */ 894 c = (volatile struct chiptime *)MACH_CLOCK_ADDR; 895 c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT; 896 i = c->regc; 897 spl0(); /* safe to turn interrupts on now */ 898 return (i); 899 } 900 901 /* 902 * Convert an ASCII string into an integer. 903 */ 904 int 905 atoi(s) 906 char *s; 907 { 908 int c; 909 unsigned base = 10, d; 910 int neg = 0, val = 0; 911 912 if (s == 0 || (c = *s++) == 0) 913 goto out; 914 915 /* skip spaces if any */ 916 while (c == ' ' || c == '\t') 917 c = *s++; 918 919 /* parse sign, allow more than one (compat) */ 920 while (c == '-') { 921 neg = !neg; 922 c = *s++; 923 } 924 925 /* parse base specification, if any */ 926 if (c == '0') { 927 c = *s++; 928 switch (c) { 929 case 'X': 930 case 'x': 931 base = 16; 932 break; 933 case 'B': 934 case 'b': 935 base = 2; 936 break; 937 default: 938 base = 8; 939 break; 940 } 941 } 942 943 /* parse number proper */ 944 for (;;) { 945 if (c >= '0' && c <= '9') 946 d = c - '0'; 947 else if (c >= 'a' && c <= 'z') 948 d = c - 'a' + 10; 949 else if (c >= 'A' && c <= 'Z') 950 d = c - 'A' + 10; 951 else 952 break; 953 val *= base; 954 val += d; 955 c = *s++; 956 } 957 if (neg) 958 val = -val; 959 out: 960 return val; 961 } 962 963 #ifdef DS5000 964 /* 965 * Mach Operating System 966 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 967 * All Rights Reserved. 968 * 969 * Permission to use, copy, modify and distribute this software and its 970 * documentation is hereby granted, provided that both the copyright 971 * notice and this permission notice appear in all copies of the 972 * software, derivative works or modified versions, and any portions 973 * thereof, and that both notices appear in supporting documentation. 974 * 975 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 976 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 977 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 978 * 979 * Carnegie Mellon requests users of this software to return to 980 * 981 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 982 * School of Computer Science 983 * Carnegie Mellon University 984 * Pittsburgh PA 15213-3890 985 * 986 * any improvements or extensions that they make and grant Carnegie the 987 * rights to redistribute these changes. 988 */ 989 990 #include "turbochannel.h" 991 992 /* 993 * Driver map: associates a device driver to an option type. 994 * Drivers name are (arbitrarily) defined in each driver and 995 * used in the various config tables. 996 */ 997 struct drivers_map { 998 char module_name[TC_ROM_LLEN]; /* from ROM, literally! */ 999 char *driver_name; /* in bus_??_init[] tables */ 1000 } tc_drivers_map[] = { 1001 { "KN02 ", "dc"}, /* system board, serial I/O */ 1002 { "PMAD-AA ", "le"}, /* Ether */ 1003 { "PMAZ-AA ", "asc"}, /* SCSI */ 1004 { "PMAG-BA ", "cfb"}, /* Color Frame Buffer */ 1005 { "PMAG-CA ", "ga"}, /* 2D graphic board */ 1006 { "PMAG-DA ", "gq"}, /* 3D graphic board (LM) */ 1007 { "PMAG-FA ", "gq"}, /* 3D graphic board (HE) */ 1008 1009 { "", 0} /* list end */ 1010 }; 1011 1012 #ifdef DEBUG 1013 int tc_verbose = 0; 1014 #endif 1015 1016 /* 1017 * TURBOchannel autoconf procedure. Finds in one sweep what is 1018 * hanging on the bus and fills in the tc_slot_info array. 1019 * This is only the first part of the autoconf scheme, at this 1020 * time we are basically only looking for a graphics board and 1021 * serial port to use as system console (all workstations). 1022 * 1023 * XXX Someday make number of slots dynamic too. 1024 */ 1025 1026 #define KN02_TC_NSLOTS 8 1027 1028 tc_option_t tc_slot_info[KN02_TC_NSLOTS]; 1029 1030 caddr_t tc_slot_virt_addr[] = { 1031 (caddr_t)0xbe000000, /* TURBOchannel, slot 0 */ 1032 (caddr_t)0xbe400000, /* TURBOchannel, slot 1 */ 1033 (caddr_t)0xbe800000, /* TURBOchannel, slot 2 */ 1034 (caddr_t)0xbec00000, /* TURBOchannel, slot 3 */ 1035 (caddr_t)0xbf000000, /* TURBOchannel, slot 4 */ 1036 (caddr_t)0xbf400000, /* TURBOchannel, slot 5 */ 1037 (caddr_t)0xbf800000, /* TURBOchannel, slot 6 */ 1038 /* (caddr_t)0xbfc00000, TURBOchannel, slot 7 */ 1039 }; 1040 1041 void 1042 tc_find_all_options() 1043 { 1044 register int i; 1045 caddr_t addr; 1046 register tc_option_t *sl; 1047 register struct drivers_map *map; 1048 register struct pmax_ctlr *cp; 1049 register struct driver *drp; 1050 1051 /* 1052 * Look for all controllers on the bus. 1053 */ 1054 i = sizeof(tc_slot_virt_addr) / sizeof(tc_slot_virt_addr[0]) - 1; 1055 while (i >= 0) { 1056 addr = tc_slot_virt_addr[i]; 1057 if (tc_probe_slot(addr, &tc_slot_info[i])) { 1058 /* 1059 * Found a slot, make a note of it 1060 */ 1061 tc_slot_info[i].present = 1; 1062 tc_slot_info[i].module_address = addr; 1063 } 1064 1065 i -= tc_slot_info[i].slot_size; 1066 } 1067 1068 /* 1069 * Now for each slot found, see if we have a device driver that 1070 * handles it. 1071 */ 1072 for (i = 0, sl = tc_slot_info; i < KN02_TC_NSLOTS; i++, sl++) { 1073 if (!sl->present) 1074 continue; 1075 /* 1076 * Look for mapping between the module name and 1077 * the device driver name. 1078 */ 1079 for (map = tc_drivers_map; map->driver_name; map++) { 1080 if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN)) 1081 continue; 1082 goto fnd_map; 1083 } 1084 if (tc_verbose) 1085 printf("Cannot associate a device driver to %s\n", 1086 sl->module_name); 1087 sl->present = 0; 1088 continue; 1089 1090 /* 1091 * Find the device driver entry and fill in the address. 1092 */ 1093 fnd_map: 1094 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) { 1095 if (strcmp(drp->d_name, map->driver_name)) 1096 continue; 1097 if (cp->pmax_addr == (char *)QUES) { 1098 cp->pmax_addr = sl->module_address; 1099 cp->pmax_pri = i; 1100 continue; 1101 } 1102 if (cp->pmax_addr != sl->module_address) { 1103 cp->pmax_addr = (char *)QUES; 1104 printf("%s: device not at configued address (expected at %x, found at %x)\n", 1105 drp->d_name, 1106 cp->pmax_addr, sl->module_address); 1107 } 1108 } 1109 } 1110 } 1111 1112 /* 1113 * Probe a slot in the TURBOchannel. Return TRUE if a valid option 1114 * is present, FALSE otherwise. A side-effect is to fill the slot 1115 * descriptor with the size of the option, whether it is 1116 * recognized or not. 1117 */ 1118 int 1119 tc_probe_slot(addr, slot) 1120 caddr_t addr; 1121 tc_option_t *slot; 1122 { 1123 int i; 1124 static unsigned tc_offset_rom[] = { 1125 TC_OFF_PROTO_ROM, TC_OFF_ROM 1126 }; 1127 #define TC_N_OFFSETS sizeof(tc_offset_rom)/sizeof(unsigned) 1128 1129 slot->slot_size = 1; 1130 1131 for (i = 0; i < TC_N_OFFSETS; i++) { 1132 if (badaddr(addr + tc_offset_rom[i], 4)) 1133 continue; 1134 /* complain only on last chance */ 1135 if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]), 1136 slot, i == (TC_N_OFFSETS-1))) 1137 return (1); 1138 } 1139 return (0); 1140 #undef TC_N_OFFSETS 1141 } 1142 1143 /* 1144 * Identify an option on the TURBOchannel. Looks at the mandatory 1145 * info in the option's ROM and checks it. 1146 */ 1147 int 1148 tc_identify_option(addr, slot, complain) 1149 tc_rommap_t *addr; 1150 tc_option_t *slot; 1151 int complain; 1152 { 1153 register int i; 1154 unsigned char width; 1155 char firmwr[TC_ROM_LLEN+1]; 1156 char vendor[TC_ROM_LLEN+1]; 1157 char module[TC_ROM_LLEN+1]; 1158 char host_type[TC_ROM_SLEN+1]; 1159 1160 /* 1161 * We do not really use the 'width' info, but take advantage 1162 * of the restriction that the spec impose on the portion 1163 * of the ROM that maps between +0x3e0 and +0x470, which 1164 * is the only piece we need to look at. 1165 */ 1166 width = addr->rom_width.value; 1167 switch (width) { 1168 case 1: 1169 case 2: 1170 case 4: 1171 break; 1172 1173 default: 1174 if (complain) 1175 printf("Invalid ROM width (0x%x) at x%x\n", 1176 width, addr); 1177 return (0); 1178 } 1179 1180 if (addr->rom_stride.value != 4) { 1181 if (complain) 1182 printf("Invalid ROM stride (0x%x) at x%x\n", 1183 addr->rom_stride.value, addr); 1184 return (0); 1185 } 1186 1187 if (addr->test_data[0] != 0x55 || 1188 addr->test_data[4] != 0x00 || 1189 addr->test_data[8] != 0xaa || 1190 addr->test_data[12] != 0xff) { 1191 if (complain) 1192 printf("Test pattern failed, option at x%x\n", 1193 addr); 1194 return (0); 1195 } 1196 1197 for (i = 0; i < TC_ROM_LLEN; i++) { 1198 firmwr[i] = addr->firmware_rev[i].value; 1199 vendor[i] = addr->vendor_name[i].value; 1200 module[i] = addr->module_name[i].value; 1201 if (i >= TC_ROM_SLEN) 1202 continue; 1203 host_type[i] = addr->host_firmware_type[i].value; 1204 } 1205 1206 if (tc_verbose) { 1207 firmwr[TC_ROM_LLEN] = '\0'; 1208 vendor[TC_ROM_LLEN] = '\0'; 1209 module[TC_ROM_LLEN] = '\0'; 1210 host_type[TC_ROM_SLEN] = '\0'; 1211 printf("%s %s '%s' at x%x\n %s %s %s '%s'\n %s %d %s %d %s\n", 1212 "Found a", vendor, module, addr, 1213 "Firmware rev.", firmwr, 1214 "diagnostics for a", host_type, 1215 "ROM size is", addr->rom_size.value << 3, 1216 "Kbytes, uses", addr->slot_size.value, "TC slot(s)"); 1217 } 1218 1219 bcopy(module, slot->module_name, TC_ROM_LLEN); 1220 bcopy(vendor, slot->module_id, TC_ROM_LLEN); 1221 bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN); 1222 slot->slot_size = addr->slot_size.value; 1223 slot->rom_width = width; 1224 1225 return (1); 1226 } 1227 1228 /* 1229 * Enable/Disable interrupts for a TURBOchannel slot. 1230 */ 1231 tc_enable_interrupt(slotno, on) 1232 register int slotno; 1233 int on; 1234 { 1235 register volatile int *p_csr = (volatile int *)MACH_SYS_CSR_ADDR; 1236 int csr; 1237 int s; 1238 1239 slotno = 1 << (slotno + MACH_CSR_IOINTEN_SHIFT); 1240 s = Mach_spl0(); 1241 csr = *p_csr & ~(MACH_CSR_MBZ | 0xFF); 1242 if (on) 1243 *p_csr = csr | slotno; 1244 else 1245 *p_csr = csr & ~slotno; 1246 splx(s); 1247 } 1248 1249 #endif /* DS5000 */ 1250