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