1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. 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 8.5 (Berkeley) 06/02/95 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/ioctl.h> 34 #include <sys/tty.h> 35 #include <sys/user.h> 36 #include <sys/exec.h> 37 #include <sys/sysctl.h> 38 #include <sys/mount.h> 39 #include <sys/syscallargs.h> 40 #ifdef SYSVSHM 41 #include <sys/shm.h> 42 #endif 43 44 #include <vm/vm_kern.h> 45 46 #include <machine/cpu.h> 47 #include <machine/reg.h> 48 #include <machine/psl.h> 49 #include <machine/pte.h> 50 #include <machine/dc7085cons.h> 51 52 #include <pmax/stand/dec_prom.h> 53 54 #include <pmax/dev/device.h> 55 #include <pmax/dev/sccreg.h> 56 #include <pmax/dev/ascreg.h> 57 58 #include <pmax/pmax/clockreg.h> 59 #include <pmax/pmax/kn01.h> 60 #include <pmax/pmax/kn02.h> 61 #include <pmax/pmax/kmin.h> 62 #include <pmax/pmax/maxine.h> 63 #include <pmax/pmax/kn03.h> 64 #include <pmax/pmax/asic.h> 65 #include <pmax/pmax/turbochannel.h> 66 #include <pmax/pmax/pmaxtype.h> 67 #include <pmax/pmax/cons.h> 68 69 #include <pm.h> 70 #include <cfb.h> 71 #include <mfb.h> 72 #include <xcfb.h> 73 #include <dc.h> 74 #include <dtop.h> 75 #include <scc.h> 76 #include <le.h> 77 #include <asc.h> 78 79 #if NDC > 0 80 extern int dcGetc(), dcparam(); 81 extern void dcPutc(); 82 #endif 83 #if NDTOP > 0 84 extern int dtopKBDGetc(); 85 #endif 86 #if NSCC > 0 87 extern int sccGetc(), sccparam(); 88 extern void sccPutc(); 89 #endif 90 extern int KBDGetc(); 91 extern void fbPutc(); 92 extern struct consdev cn_tab; 93 94 /* Will scan from max to min, inclusive */ 95 static int tc_max_slot = KN02_TC_MAX; 96 static int tc_min_slot = KN02_TC_MIN; 97 static u_int tc_slot_phys_base [TC_MAX_SLOTS] = { 98 /* use 3max for default values */ 99 KN02_PHYS_TC_0_START, KN02_PHYS_TC_1_START, 100 KN02_PHYS_TC_2_START, KN02_PHYS_TC_3_START, 101 KN02_PHYS_TC_4_START, KN02_PHYS_TC_5_START, 102 KN02_PHYS_TC_6_START, KN02_PHYS_TC_7_START 103 }; 104 105 /* the following is used externally (sysctl_hw) */ 106 char machine[] = "DEC"; /* cpu "architecture" */ 107 char cpu_model[30]; 108 109 vm_map_t buffer_map; 110 111 /* 112 * Declare these as initialized data so we can patch them. 113 */ 114 int nswbuf = 0; 115 #ifdef NBUF 116 int nbuf = NBUF; 117 #else 118 int nbuf = 0; 119 #endif 120 #ifdef BUFPAGES 121 int bufpages = BUFPAGES; 122 #else 123 int bufpages = 0; 124 #endif 125 int msgbufmapped = 0; /* set when safe to use msgbuf */ 126 int maxmem; /* max memory per process */ 127 int physmem; /* max supported memory, changes to actual */ 128 int pmax_boardtype; /* Mother board type */ 129 u_long le_iomem; /* 128K for lance chip via. ASIC */ 130 u_long asc_iomem; /* and 7 * 8K buffers for the scsi */ 131 u_long asic_base; /* Base address of I/O asic */ 132 const struct callback *callv; /* pointer to PROM entry points */ 133 134 void (*tc_enable_interrupt)(); 135 extern int (*pmax_hardware_intr)(); 136 void pmax_slot_hand_fill(); 137 int kn02_intr(), kmin_intr(), xine_intr(), pmax_intr(); 138 #ifdef DS5000_240 139 int kn03_intr(); 140 #endif 141 extern int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3(), splhigh(); 142 int (*Mach_splnet)() = splhigh; 143 int (*Mach_splbio)() = splhigh; 144 int (*Mach_splimp)() = splhigh; 145 int (*Mach_spltty)() = splhigh; 146 int (*Mach_splclock)() = splhigh; 147 int (*Mach_splstatclock)() = splhigh; 148 void (*tc_slot_hand_fill)(); 149 extern volatile struct chiptime *Mach_clock_addr; 150 u_long kmin_tc3_imask, xine_tc3_imask; 151 #ifdef DS5000_240 152 u_long kn03_tc3_imask; 153 #endif 154 tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS]; 155 static void asic_init(); 156 extern void RemconsInit(); 157 #ifdef DS5000 158 void kn02_enable_intr(), kn02_slot_hand_fill(), 159 kmin_enable_intr(), kmin_slot_hand_fill(), 160 xine_enable_intr(), xine_slot_hand_fill(), 161 tc_find_all_options(); 162 #ifdef DS5000_240 163 void kn03_enable_intr(), kn03_slot_hand_fill(); 164 #endif 165 #endif /* DS5000 */ 166 167 /* 168 * safepri is a safe priority for sleep to set for a spin-wait 169 * during autoconfiguration or after a panic. 170 */ 171 int safepri = PSL_LOWIPL; 172 173 struct user *proc0paddr; 174 struct proc nullproc; /* for use by swtch_exit() */ 175 176 /* 177 * Do all the stuff that locore normally does before calling main(). 178 * Process arguments passed to us by the prom monitor. 179 * Return the first page address following the system. 180 */ 181 mach_init(argc, argv, code, cv) 182 int argc; 183 char *argv[]; 184 u_int code; 185 const struct callback *cv; 186 { 187 register char *cp; 188 register int i; 189 register unsigned firstaddr; 190 register caddr_t v; 191 caddr_t start; 192 extern char edata[], end[]; 193 extern char MachUTLBMiss[], MachUTLBMissEnd[]; 194 extern char MachException[], MachExceptionEnd[]; 195 196 /* clear the BSS segment */ 197 v = (caddr_t)pmax_round_page(end); 198 bzero(edata, v - edata); 199 200 /* check for direct boot from DS5000 PROM */ 201 if (argc > 0 && strcmp(argv[0], "boot") == 0) { 202 argc--; 203 argv++; 204 } 205 206 /* look at argv[0] and compute bootdev */ 207 makebootdev(argv[0]); 208 209 /* 210 * Look at arguments passed to us and compute boothowto. 211 */ 212 #ifdef GENERIC 213 boothowto = RB_SINGLE | RB_ASKNAME; 214 #else 215 boothowto = RB_SINGLE; 216 #endif 217 #ifdef KADB 218 boothowto |= RB_KDB; 219 #endif 220 if (argc > 1) { 221 for (i = 1; i < argc; i++) { 222 for (cp = argv[i]; *cp; cp++) { 223 switch (*cp) { 224 case 'a': /* autoboot */ 225 boothowto &= ~RB_SINGLE; 226 break; 227 228 case 'd': /* use compiled in default root */ 229 boothowto |= RB_DFLTROOT; 230 break; 231 232 case 'm': /* mini root present in memory */ 233 boothowto |= RB_MINIROOT; 234 break; 235 236 case 'n': /* ask for names */ 237 boothowto |= RB_ASKNAME; 238 break; 239 240 case 'N': /* don't ask for names */ 241 boothowto &= ~RB_ASKNAME; 242 } 243 } 244 } 245 } 246 247 #ifdef MFS 248 /* 249 * Check to see if a mini-root was loaded into memory. It resides 250 * at the start of the next page just after the end of BSS. 251 */ 252 if (boothowto & RB_MINIROOT) { 253 boothowto |= RB_DFLTROOT; 254 v += mfs_initminiroot(v); 255 } 256 #endif 257 258 /* 259 * Init mapping for u page(s) for proc[0], pm_tlbpid 1. 260 */ 261 start = v; 262 curproc->p_addr = proc0paddr = (struct user *)v; 263 curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs; 264 firstaddr = MACH_CACHED_TO_PHYS(v); 265 for (i = 0; i < UPAGES; i++) { 266 MachTLBWriteIndexed(i, 267 (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT), 268 curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M); 269 firstaddr += NBPG; 270 } 271 v += UPAGES * NBPG; 272 MachSetPID(1); 273 274 /* 275 * init nullproc for swtch_exit(). 276 * init mapping for u page(s), pm_tlbpid 0 277 * This could be used for an idle process. 278 */ 279 nullproc.p_addr = (struct user *)v; 280 nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs; 281 bcopy("nullproc", nullproc.p_comm, sizeof("nullproc")); 282 for (i = 0; i < UPAGES; i++) { 283 nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M; 284 firstaddr += NBPG; 285 } 286 v += UPAGES * NBPG; 287 288 /* clear pages for u areas */ 289 bzero(start, v - start); 290 291 /* 292 * Copy down exception vector code. 293 */ 294 if (MachUTLBMissEnd - MachUTLBMiss > 0x80) 295 panic("startup: UTLB code too large"); 296 bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC, 297 MachUTLBMissEnd - MachUTLBMiss); 298 bcopy(MachException, (char *)MACH_GEN_EXC_VEC, 299 MachExceptionEnd - MachException); 300 301 /* 302 * Clear out the I and D caches. 303 */ 304 MachConfigCache(); 305 MachFlushCache(); 306 307 /* 308 * Determine what model of computer we are running on. 309 */ 310 if (code == DEC_PROM_MAGIC) { 311 callv = cv; 312 i = (*cv->getsysid)(); 313 cp = ""; 314 } else { 315 callv = &callvec; 316 if (cp = (*callv->getenv)("systype")) 317 i = atoi(cp); 318 else { 319 cp = ""; 320 i = 0; 321 } 322 } 323 /* check for MIPS based platform */ 324 if (((i >> 24) & 0xFF) != 0x82) { 325 printf("Unknown System type '%s' 0x%x\n", cp, i); 326 boot(RB_HALT | RB_NOSYNC); 327 } 328 329 /* check what model platform we are running on */ 330 pmax_boardtype = ((i >> 16) & 0xff); 331 switch (pmax_boardtype) { 332 case DS_PMAX: /* DS3100 Pmax */ 333 /* 334 * Set up interrupt handling and I/O addresses. 335 */ 336 pmax_hardware_intr = pmax_intr; 337 Mach_splnet = Mach_spl1; 338 Mach_splbio = Mach_spl0; 339 Mach_splimp = Mach_spl1; 340 Mach_spltty = Mach_spl2; 341 Mach_splclock = Mach_spl3; 342 Mach_splstatclock = Mach_spl3; 343 Mach_clock_addr = (volatile struct chiptime *) 344 MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK); 345 pmax_slot_hand_fill(); 346 strcpy(cpu_model, "3100"); 347 break; 348 349 #ifdef DS5000 350 case DS_3MAX: /* DS5000/200 3max */ 351 { 352 volatile int *csr_addr = 353 (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR); 354 355 /* 356 * Enable ECC memory correction, turn off LEDs, and 357 * disable all TURBOchannel interrupts. 358 */ 359 i = *csr_addr; 360 *csr_addr = (i & ~(KN02_CSR_WRESERVED | KN02_CSR_IOINTEN)) | 361 KN02_CSR_CORRECT | 0xff; 362 363 tc_slot_hand_fill = kn02_slot_hand_fill; 364 pmax_hardware_intr = kn02_intr; 365 tc_enable_interrupt = kn02_enable_intr; 366 Mach_splnet = Mach_spl0; 367 Mach_splbio = Mach_spl0; 368 Mach_splimp = Mach_spl0; 369 Mach_spltty = Mach_spl0; 370 Mach_splclock = Mach_spl1; 371 Mach_splstatclock = Mach_spl1; 372 Mach_clock_addr = (volatile struct chiptime *) 373 MACH_PHYS_TO_UNCACHED(KN02_SYS_CLOCK); 374 375 /* 376 * Probe the TURBOchannel to see what controllers are present. 377 */ 378 tc_find_all_options(); 379 380 /* clear any memory errors from probes */ 381 *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0; 382 } 383 strcpy(cpu_model, "5000/200"); 384 break; 385 386 case DS_3MIN: /* DS5000/1xx 3min */ 387 tc_max_slot = KMIN_TC_MAX; 388 tc_min_slot = KMIN_TC_MIN; 389 tc_slot_phys_base[0] = KMIN_PHYS_TC_0_START; 390 tc_slot_phys_base[1] = KMIN_PHYS_TC_1_START; 391 tc_slot_phys_base[2] = KMIN_PHYS_TC_2_START; 392 asic_base = MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC); 393 tc_slot_hand_fill = kmin_slot_hand_fill; 394 pmax_hardware_intr = kmin_intr; 395 tc_enable_interrupt = kmin_enable_intr; 396 kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN | 397 KMIN_INTR_TIMEOUT); 398 399 /* 400 * Since all the motherboard interrupts come through the 401 * I/O ASIC, it has to be turned off for all the spls and 402 * since we don't know what kinds of devices are in the 403 * turbochannel option slots, just splhigh(). 404 */ 405 Mach_splnet = splhigh; 406 Mach_splbio = splhigh; 407 Mach_splimp = splhigh; 408 Mach_spltty = splhigh; 409 Mach_splclock = splhigh; 410 Mach_splstatclock = splhigh; 411 Mach_clock_addr = (volatile struct chiptime *) 412 MACH_PHYS_TO_UNCACHED(KMIN_SYS_CLOCK); 413 414 /* 415 * Probe the TURBOchannel to see what controllers are present. 416 */ 417 tc_find_all_options(); 418 419 /* 420 * Initialize interrupts. 421 */ 422 *(u_int *)ASIC_REG_IMSK(asic_base) = KMIN_IM0; 423 *(u_int *)ASIC_REG_INTR(asic_base) = 0; 424 /* clear any memory errors from probes */ 425 *(unsigned *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0; 426 strcpy(cpu_model, "5000/1xx"); 427 break; 428 429 case DS_MAXINE: /* DS5000/xx maxine */ 430 tc_max_slot = XINE_TC_MAX; 431 tc_min_slot = XINE_TC_MIN; 432 tc_slot_phys_base[0] = XINE_PHYS_TC_0_START; 433 tc_slot_phys_base[1] = XINE_PHYS_TC_1_START; 434 asic_base = MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC); 435 tc_slot_hand_fill = xine_slot_hand_fill; 436 pmax_hardware_intr = xine_intr; 437 tc_enable_interrupt = xine_enable_intr; 438 Mach_splnet = Mach_spl3; 439 Mach_splbio = Mach_spl3; 440 Mach_splimp = Mach_spl3; 441 Mach_spltty = Mach_spl3; 442 Mach_splclock = Mach_spl1; 443 Mach_splstatclock = Mach_spl1; 444 Mach_clock_addr = (volatile struct chiptime *) 445 MACH_PHYS_TO_UNCACHED(XINE_SYS_CLOCK); 446 447 /* 448 * Probe the TURBOchannel to see what controllers are present. 449 */ 450 tc_find_all_options(); 451 452 /* 453 * Initialize interrupts. 454 */ 455 *(u_int *)ASIC_REG_IMSK(asic_base) = XINE_IM0; 456 *(u_int *)ASIC_REG_INTR(asic_base) = 0; 457 /* clear any memory errors from probes */ 458 *(unsigned *)MACH_PHYS_TO_UNCACHED(XINE_REG_TIMEOUT) = 0; 459 strcpy(cpu_model, "5000/25"); 460 break; 461 462 #ifdef DS5000_240 463 case DS_3MAXPLUS: /* DS5000/240 3max+ UNTESTED!! */ 464 tc_max_slot = KN03_TC_MAX; 465 tc_min_slot = KN03_TC_MIN; 466 tc_slot_phys_base[0] = KN03_PHYS_TC_0_START; 467 tc_slot_phys_base[1] = KN03_PHYS_TC_1_START; 468 tc_slot_phys_base[2] = KN03_PHYS_TC_2_START; 469 asic_base = MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC); 470 tc_slot_hand_fill = kn03_slot_hand_fill; 471 pmax_hardware_intr = kn03_intr; 472 tc_enable_interrupt = kn03_enable_intr; 473 kn03_tc3_imask = KN03_INTR_PSWARN; 474 475 Mach_splnet = Mach_spl0; 476 Mach_splbio = Mach_spl0; 477 Mach_splimp = Mach_spl0; 478 Mach_spltty = Mach_spl0; 479 Mach_splclock = Mach_spl1; 480 Mach_splstatclock = Mach_spl1; 481 Mach_clock_addr = (volatile struct chiptime *) 482 MACH_PHYS_TO_UNCACHED(KN03_SYS_CLOCK); 483 484 /* 485 * Probe the TURBOchannel to see what controllers are present. 486 */ 487 tc_find_all_options(); 488 489 /* 490 * Initialize interrupts. 491 */ 492 *(u_int *)ASIC_REG_IMSK(asic_base) = KN03_IM0; 493 *(u_int *)ASIC_REG_INTR(asic_base) = 0; 494 /* clear any memory errors from probes */ 495 *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0; 496 strcpy(cpu_model, "5000/240"); 497 break; 498 #endif /* DS5000_240 */ 499 #endif /* DS5000 */ 500 501 default: 502 printf("kernel not configured for systype 0x%x\n", i); 503 boot(RB_HALT | RB_NOSYNC); 504 } 505 506 /* 507 * Find out how much memory is available. 508 * Be careful to save and restore the original contents for msgbuf. 509 */ 510 physmem = btoc(v - KERNBASE); 511 cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT); 512 while (cp < (char *)MACH_MAX_MEM_ADDR) { 513 if (badaddr(cp, 4)) 514 break; 515 i = *(int *)cp; 516 *(int *)cp = 0xa5a5a5a5; 517 /* 518 * Data will persist on the bus if we read it right away. 519 * Have to be tricky here. 520 */ 521 ((int *)cp)[4] = 0x5a5a5a5a; 522 MachEmptyWriteBuffer(); 523 if (*(int *)cp != 0xa5a5a5a5) 524 break; 525 *(int *)cp = i; 526 cp += NBPG; 527 physmem++; 528 } 529 530 maxmem = physmem; 531 532 #if NLE > 0 533 /* 534 * Grab 128K at the top of physical memory for the lance chip 535 * on machines where it does dma through the I/O ASIC. 536 * It must be physically contiguous and aligned on a 128K boundary. 537 */ 538 if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE || 539 pmax_boardtype == DS_3MAXPLUS) { 540 maxmem -= btoc(128 * 1024); 541 le_iomem = (maxmem << PGSHIFT); 542 } 543 #endif /* NLE */ 544 #if NASC > 0 545 /* 546 * Ditto for the scsi chip. There is probably a way to make asc.c 547 * do dma without these buffers, but it would require major 548 * re-engineering of the asc driver. 549 * They must be 8K in size and page aligned. 550 */ 551 if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE || 552 pmax_boardtype == DS_3MAXPLUS) { 553 maxmem -= btoc(ASC_NCMD * 8192); 554 asc_iomem = (maxmem << PGSHIFT); 555 } 556 #endif /* NASC */ 557 558 /* 559 * Initialize error message buffer (at end of core). 560 */ 561 maxmem -= btoc(sizeof (struct msgbuf)); 562 msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT)); 563 msgbufmapped = 1; 564 565 /* 566 * Allocate space for system data structures. 567 * The first available kernel virtual address is in "v". 568 * As pages of kernel virtual memory are allocated, "v" is incremented. 569 * 570 * These data structures are allocated here instead of cpu_startup() 571 * because physical memory is directly addressable. We don't have 572 * to map these into virtual address space. 573 */ 574 start = v; 575 576 #define valloc(name, type, num) \ 577 (name) = (type *)v; v = (caddr_t)((name)+(num)) 578 #define valloclim(name, type, num, lim) \ 579 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 580 valloc(cfree, struct cblock, nclist); 581 valloc(callout, struct callout, ncallout); 582 valloc(swapmap, struct map, nswapmap = maxproc * 2); 583 #ifdef SYSVSHM 584 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 585 #endif 586 587 /* 588 * Determine how many buffers to allocate. 589 * We allocate more buffer space than the BSD standard of 590 * using 10% of memory for the first 2 Meg, 5% of remaining. 591 * We just allocate a flat 10%. Ensure a minimum of 16 buffers. 592 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 593 */ 594 if (bufpages == 0) 595 bufpages = physmem / 10 / CLSIZE; 596 if (nbuf == 0) { 597 nbuf = bufpages; 598 if (nbuf < 16) 599 nbuf = 16; 600 } 601 if (nswbuf == 0) { 602 nswbuf = (nbuf / 2) &~ 1; /* force even */ 603 if (nswbuf > 256) 604 nswbuf = 256; /* sanity */ 605 } 606 valloc(swbuf, struct buf, nswbuf); 607 valloc(buf, struct buf, nbuf); 608 609 /* 610 * Clear allocated memory. 611 */ 612 bzero(start, v - start); 613 614 /* 615 * Initialize the virtual memory system. 616 */ 617 pmap_bootstrap((vm_offset_t)v); 618 } 619 620 /* 621 * Console initialization: called early on from main, 622 * before vm init or startup. Do enough configuration 623 * to choose and initialize a console. 624 */ 625 consinit() 626 { 627 register int kbd, crt; 628 register char *oscon; 629 630 /* 631 * First get the "osconsole" environment variable. 632 */ 633 oscon = (*callv->getenv)("osconsole"); 634 crt = kbd = -1; 635 if (oscon && *oscon >= '0' && *oscon <= '9') { 636 kbd = *oscon - '0'; 637 cn_tab.cn_screen = 0; 638 while (*++oscon) { 639 if (*oscon == ',') 640 cn_tab.cn_screen = 1; 641 else if (cn_tab.cn_screen && 642 *oscon >= '0' && *oscon <= '9') { 643 crt = kbd; 644 kbd = *oscon - '0'; 645 break; 646 } 647 } 648 } 649 if (pmax_boardtype == DS_PMAX && kbd == 1) 650 cn_tab.cn_screen = 1; 651 /* 652 * The boot program uses PMAX ROM entrypoints so the ROM sets 653 * osconsole to '1' like the PMAX. 654 */ 655 if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) { 656 cn_tab.cn_screen = 1; 657 crt = 0; 658 kbd = 7; 659 } 660 661 /* 662 * First try the keyboard/crt cases then fall through to the 663 * remote serial lines. 664 */ 665 if (cn_tab.cn_screen) { 666 switch (pmax_boardtype) { 667 case DS_PMAX: 668 #if NDC > 0 && NPM > 0 669 if (pminit()) { 670 cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT); 671 cn_tab.cn_getc = KBDGetc; 672 cn_tab.cn_kbdgetc = dcGetc; 673 cn_tab.cn_putc = fbPutc; 674 cn_tab.cn_disabled = 0; 675 return; 676 } 677 #endif /* NDC and NPM */ 678 goto remcons; 679 680 case DS_MAXINE: 681 #if NDTOP > 0 682 if (kbd == 3) { 683 cn_tab.cn_dev = makedev(DTOPDEV, 0); 684 cn_tab.cn_getc = dtopKBDGetc; 685 cn_tab.cn_putc = fbPutc; 686 } else 687 #endif /* NDTOP */ 688 goto remcons; 689 #if NXCFB > 0 690 if (crt == 3 && xcfbinit()) { 691 cn_tab.cn_disabled = 0; 692 return; 693 } 694 #endif /* XCFB */ 695 break; 696 697 case DS_3MAX: 698 #if NDC > 0 699 if (kbd == 7) { 700 cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT); 701 cn_tab.cn_getc = KBDGetc; 702 cn_tab.cn_kbdgetc = dcGetc; 703 cn_tab.cn_putc = fbPutc; 704 } else 705 #endif /* NDC */ 706 goto remcons; 707 break; 708 709 case DS_3MIN: 710 case DS_3MAXPLUS: 711 #if NSCC > 0 712 if (kbd == 3) { 713 cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT); 714 cn_tab.cn_getc = KBDGetc; 715 cn_tab.cn_kbdgetc = sccGetc; 716 cn_tab.cn_putc = fbPutc; 717 } else 718 #endif /* NSCC */ 719 goto remcons; 720 break; 721 722 default: 723 goto remcons; 724 }; 725 726 /* 727 * Check for a suitable turbochannel frame buffer. 728 */ 729 if (tc_slot_info[crt].driver_name) { 730 #if NMFB > 0 731 if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 && 732 mfbinit(tc_slot_info[crt].k1seg_address)) { 733 cn_tab.cn_disabled = 0; 734 return; 735 } 736 #endif /* NMFB */ 737 #if NCFB > 0 738 if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 && 739 cfbinit(tc_slot_info[crt].k1seg_address)) { 740 cn_tab.cn_disabled = 0; 741 return; 742 } 743 #endif /* NCFB */ 744 printf("crt: %s not supported as console device\n", 745 tc_slot_info[crt].driver_name); 746 } else 747 printf("No crt console device in slot %d\n", crt); 748 } 749 remcons: 750 /* 751 * Configure a serial port as a remote console. 752 */ 753 cn_tab.cn_screen = 0; 754 switch (pmax_boardtype) { 755 case DS_PMAX: 756 #if NDC > 0 757 if (kbd == 4) 758 cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT); 759 else 760 cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT); 761 cn_tab.cn_getc = dcGetc; 762 cn_tab.cn_putc = dcPutc; 763 #endif /* NDC */ 764 break; 765 766 case DS_3MAX: 767 #if NDC > 0 768 cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT); 769 cn_tab.cn_getc = dcGetc; 770 cn_tab.cn_putc = dcPutc; 771 #endif /* NDC */ 772 break; 773 774 case DS_3MIN: 775 case DS_3MAXPLUS: 776 #if NSCC > 0 777 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT); 778 cn_tab.cn_getc = sccGetc; 779 cn_tab.cn_putc = sccPutc; 780 #endif /* NSCC */ 781 break; 782 783 case DS_MAXINE: 784 #if NSCC > 0 785 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT); 786 cn_tab.cn_getc = sccGetc; 787 cn_tab.cn_putc = sccPutc; 788 #endif /* NSCC */ 789 break; 790 }; 791 if (cn_tab.cn_dev == NODEV) 792 printf("Can't configure console!\n"); 793 } 794 795 /* 796 * cpu_startup: allocate memory for variable-sized tables, 797 * initialize cpu, and do autoconfiguration. 798 */ 799 cpu_startup() 800 { 801 register unsigned i; 802 register caddr_t v; 803 int base, residual; 804 vm_offset_t minaddr, maxaddr; 805 vm_size_t size; 806 #ifdef DEBUG 807 extern int pmapdebug; 808 int opmapdebug = pmapdebug; 809 810 pmapdebug = 0; 811 #endif 812 813 /* 814 * Good {morning,afternoon,evening,night}. 815 */ 816 printf(version); 817 printf("real mem = %d\n", ctob(physmem)); 818 819 /* 820 * Allocate virtual address space for file I/O buffers. 821 * Note they are different than the array of headers, 'buf', 822 * and usually occupy more virtual memory than physical. 823 */ 824 size = MAXBSIZE * nbuf; 825 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 826 &maxaddr, size, TRUE); 827 minaddr = (vm_offset_t)buffers; 828 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 829 &minaddr, size, FALSE) != KERN_SUCCESS) 830 panic("startup: cannot allocate buffers"); 831 base = bufpages / nbuf; 832 residual = bufpages % nbuf; 833 for (i = 0; i < nbuf; i++) { 834 vm_size_t curbufsize; 835 vm_offset_t curbuf; 836 837 /* 838 * First <residual> buffers get (base+1) physical pages 839 * allocated for them. The rest get (base) physical pages. 840 * 841 * The rest of each buffer occupies virtual space, 842 * but has no physical memory allocated for it. 843 */ 844 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 845 curbufsize = CLBYTES * (i < residual ? base+1 : base); 846 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 847 vm_map_simplify(buffer_map, curbuf); 848 } 849 /* 850 * Allocate a submap for exec arguments. This map effectively 851 * limits the number of processes exec'ing at any time. 852 */ 853 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 854 16 * NCARGS, TRUE); 855 /* 856 * Allocate a submap for physio 857 */ 858 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 859 VM_PHYS_SIZE, TRUE); 860 861 /* 862 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 863 * we use the more space efficient malloc in place of kmem_alloc. 864 */ 865 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 866 M_MBUF, M_NOWAIT); 867 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 868 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 869 VM_MBUF_SIZE, FALSE); 870 /* 871 * Initialize callouts 872 */ 873 callfree = callout; 874 for (i = 1; i < ncallout; i++) 875 callout[i-1].c_next = &callout[i]; 876 callout[i-1].c_next = NULL; 877 878 #ifdef DEBUG 879 pmapdebug = opmapdebug; 880 #endif 881 printf("avail mem = %d\n", ptoa(cnt.v_free_count)); 882 printf("using %d buffers containing %d bytes of memory\n", 883 nbuf, bufpages * CLBYTES); 884 /* 885 * Set up CPU-specific registers, cache, etc. 886 */ 887 initcpu(); 888 889 /* 890 * Set up buffers, so they can be used to read disk labels. 891 */ 892 bufinit(); 893 894 /* 895 * Configure the system. 896 */ 897 configure(); 898 } 899 900 /* 901 * machine dependent system variables. 902 */ 903 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 904 int *name; 905 u_int namelen; 906 void *oldp; 907 size_t *oldlenp; 908 void *newp; 909 size_t newlen; 910 struct proc *p; 911 { 912 913 /* all sysctl names at this level are terminal */ 914 if (namelen != 1) 915 return (ENOTDIR); /* overloaded */ 916 917 switch (name[0]) { 918 case CPU_CONSDEV: 919 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab.cn_dev, 920 sizeof cn_tab.cn_dev)); 921 default: 922 return (EOPNOTSUPP); 923 } 924 /* NOTREACHED */ 925 } 926 927 /* 928 * Set registers on exec. 929 * Clear all registers except sp, pc. 930 */ 931 setregs(p, entry, retval) 932 register struct proc *p; 933 u_long entry; 934 register_t retval[2]; 935 { 936 int sp = p->p_md.md_regs[SP]; 937 extern struct proc *machFPCurProcPtr; 938 939 bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int)); 940 p->p_md.md_regs[SP] = sp; 941 p->p_md.md_regs[PC] = entry & ~3; 942 p->p_md.md_regs[PS] = PSL_USERSET; 943 p->p_md.md_flags & ~MDP_FPUSED; 944 if (machFPCurProcPtr == p) 945 machFPCurProcPtr = (struct proc *)0; 946 } 947 948 /* 949 * WARNING: code in locore.s assumes the layout shown for sf_signum 950 * thru sf_handler so... don't screw with them! 951 */ 952 struct sigframe { 953 int sf_signum; /* signo for handler */ 954 int sf_code; /* additional info for handler */ 955 struct sigcontext *sf_scp; /* context ptr for handler */ 956 sig_t sf_handler; /* handler addr for u_sigc */ 957 struct sigcontext sf_sc; /* actual context */ 958 }; 959 960 #ifdef DEBUG 961 int sigdebug = 0; 962 int sigpid = 0; 963 #define SDB_FOLLOW 0x01 964 #define SDB_KSTACK 0x02 965 #define SDB_FPSTATE 0x04 966 #endif 967 968 /* 969 * Send an interrupt to process. 970 */ 971 void 972 sendsig(catcher, sig, mask, code) 973 sig_t catcher; 974 int sig, mask; 975 u_long code; 976 { 977 register struct proc *p = curproc; 978 register struct sigframe *fp; 979 register int *regs; 980 register struct sigacts *psp = p->p_sigacts; 981 int oonstack, fsize; 982 struct sigcontext ksc; 983 extern char sigcode[], esigcode[]; 984 985 regs = p->p_md.md_regs; 986 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 987 /* 988 * Allocate and validate space for the signal handler 989 * context. Note that if the stack is in data space, the 990 * call to grow() is a nop, and the copyout() 991 * will fail if the process has not already allocated 992 * the space with a `brk'. 993 */ 994 fsize = sizeof(struct sigframe); 995 if ((psp->ps_flags & SAS_ALTSTACK) && 996 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 997 (psp->ps_sigonstack & sigmask(sig))) { 998 fp = (struct sigframe *)(psp->ps_sigstk.ss_base + 999 psp->ps_sigstk.ss_size - fsize); 1000 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 1001 } else 1002 fp = (struct sigframe *)(regs[SP] - fsize); 1003 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 1004 (void)grow(p, (unsigned)fp); 1005 #ifdef DEBUG 1006 if ((sigdebug & SDB_FOLLOW) || 1007 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1008 printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", 1009 p->p_pid, sig, &oonstack, fp, &fp->sf_sc); 1010 #endif 1011 /* 1012 * Build the signal context to be used by sigreturn. 1013 */ 1014 ksc.sc_onstack = oonstack; 1015 ksc.sc_mask = mask; 1016 ksc.sc_pc = regs[PC]; 1017 ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ 1018 bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1], 1019 sizeof(ksc.sc_regs) - sizeof(int)); 1020 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 1021 if (ksc.sc_fpused) { 1022 extern struct proc *machFPCurProcPtr; 1023 1024 /* if FPU has current state, save it first */ 1025 if (p == machFPCurProcPtr) 1026 MachSaveCurFPState(p); 1027 bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs, 1028 sizeof(ksc.sc_fpregs)); 1029 } 1030 if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) { 1031 /* 1032 * Process has trashed its stack; give it an illegal 1033 * instruction to halt it in its tracks. 1034 */ 1035 SIGACTION(p, SIGILL) = SIG_DFL; 1036 sig = sigmask(SIGILL); 1037 p->p_sigignore &= ~sig; 1038 p->p_sigcatch &= ~sig; 1039 p->p_sigmask &= ~sig; 1040 psignal(p, SIGILL); 1041 return; 1042 } 1043 /* 1044 * Build the argument list for the signal handler. 1045 */ 1046 regs[A0] = sig; 1047 regs[A1] = code; 1048 regs[A2] = (int)&fp->sf_sc; 1049 regs[A3] = (int)catcher; 1050 1051 regs[PC] = (int)catcher; 1052 regs[SP] = (int)fp; 1053 /* 1054 * Signal trampoline code is at base of user stack. 1055 */ 1056 regs[RA] = (int)PS_STRINGS - (esigcode - sigcode); 1057 #ifdef DEBUG 1058 if ((sigdebug & SDB_FOLLOW) || 1059 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 1060 printf("sendsig(%d): sig %d returns\n", 1061 p->p_pid, sig); 1062 #endif 1063 } 1064 1065 /* 1066 * System call to cleanup state after a signal 1067 * has been taken. Reset signal mask and 1068 * stack state from context left by sendsig (above). 1069 * Return to previous pc and psl as specified by 1070 * context left by sendsig. Check carefully to 1071 * make sure that the user has not modified the 1072 * psl to gain improper priviledges or to cause 1073 * a machine fault. 1074 */ 1075 /* ARGSUSED */ 1076 sigreturn(p, uap, retval) 1077 struct proc *p; 1078 struct sigreturn_args /* { 1079 syscallarg(struct sigcontext *) sigcntxp; 1080 } */ *uap; 1081 register_t *retval; 1082 { 1083 register struct sigcontext *scp; 1084 register int *regs; 1085 struct sigcontext ksc; 1086 int error; 1087 1088 scp = SCARG(uap, sigcntxp); 1089 #ifdef DEBUG 1090 if (sigdebug & SDB_FOLLOW) 1091 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 1092 #endif 1093 regs = p->p_md.md_regs; 1094 /* 1095 * Test and fetch the context structure. 1096 * We grab it all at once for speed. 1097 */ 1098 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); 1099 if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) { 1100 #ifdef DEBUG 1101 if (!(sigdebug & SDB_FOLLOW)) 1102 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 1103 printf(" old sp %x ra %x pc %x\n", 1104 regs[SP], regs[RA], regs[PC]); 1105 printf(" new sp %x ra %x pc %x err %d z %x\n", 1106 ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], 1107 error, ksc.sc_regs[ZERO]); 1108 #endif 1109 return (EINVAL); 1110 } 1111 scp = &ksc; 1112 /* 1113 * Restore the user supplied information 1114 */ 1115 if (scp->sc_onstack & 01) 1116 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 1117 else 1118 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 1119 p->p_sigmask = scp->sc_mask &~ sigcantmask; 1120 regs[PC] = scp->sc_pc; 1121 bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)®s[1], 1122 sizeof(scp->sc_regs) - sizeof(int)); 1123 if (scp->sc_fpused) 1124 bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0], 1125 sizeof(scp->sc_fpregs)); 1126 return (EJUSTRETURN); 1127 } 1128 1129 int waittime = -1; 1130 1131 boot(howto) 1132 register int howto; 1133 { 1134 struct proc *p = curproc; /* XXX */ 1135 1136 /* take a snap shot before clobbering any registers */ 1137 if (curproc) 1138 savectx(curproc->p_addr, 0); 1139 1140 #ifdef DEBUG 1141 if (panicstr) 1142 stacktrace(); 1143 #endif 1144 1145 boothowto = howto; 1146 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 1147 register struct buf *bp; 1148 int iter, nbusy; 1149 1150 waittime = 0; 1151 (void) spl0(); 1152 printf("syncing disks... "); 1153 /* 1154 * Release vnodes held by texts before sync. 1155 */ 1156 if (panicstr == 0) 1157 vnode_pager_umount(NULL); 1158 #ifdef notdef 1159 #include "fd.h" 1160 #if NFD > 0 1161 fdshutdown(); 1162 #endif 1163 #endif 1164 sync(p, (void *)NULL, (int *)NULL); 1165 /* 1166 * Unmount filesystems 1167 */ 1168 if (panicstr == 0) 1169 vfs_unmountall(); 1170 1171 for (iter = 0; iter < 20; iter++) { 1172 nbusy = 0; 1173 for (bp = &buf[nbuf]; --bp >= buf; ) 1174 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 1175 nbusy++; 1176 if (nbusy == 0) 1177 break; 1178 printf("%d ", nbusy); 1179 DELAY(40000 * iter); 1180 } 1181 if (nbusy) 1182 printf("giving up\n"); 1183 else 1184 printf("done\n"); 1185 /* 1186 * If we've been adjusting the clock, the todr 1187 * will be out of synch; adjust it now. 1188 */ 1189 resettodr(); 1190 } 1191 (void) splhigh(); /* extreme priority */ 1192 if (callv != &callvec) { 1193 if (howto & RB_HALT) 1194 (*callv->rex)('h'); 1195 else { 1196 if (howto & RB_DUMP) 1197 dumpsys(); 1198 (*callv->rex)('b'); 1199 } 1200 } else if (howto & RB_HALT) { 1201 volatile void (*f)() = (volatile void (*)())DEC_PROM_REINIT; 1202 1203 (*f)(); /* jump back to prom monitor */ 1204 } else { 1205 volatile void (*f)() = (volatile void (*)())DEC_PROM_AUTOBOOT; 1206 1207 if (howto & RB_DUMP) 1208 dumpsys(); 1209 (*f)(); /* jump back to prom monitor and do 'auto' cmd */ 1210 } 1211 /*NOTREACHED*/ 1212 } 1213 1214 int dumpmag = (int)0x8fca0101; /* magic number for savecore */ 1215 int dumpsize = 0; /* also for savecore */ 1216 long dumplo = 0; 1217 1218 dumpconf() 1219 { 1220 int nblks; 1221 1222 dumpsize = physmem; 1223 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 1224 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 1225 if (dumpsize > btoc(dbtob(nblks - dumplo))) 1226 dumpsize = btoc(dbtob(nblks - dumplo)); 1227 else if (dumplo == 0) 1228 dumplo = nblks - btodb(ctob(physmem)); 1229 } 1230 /* 1231 * Don't dump on the first CLBYTES (why CLBYTES?) 1232 * in case the dump device includes a disk label. 1233 */ 1234 if (dumplo < btodb(CLBYTES)) 1235 dumplo = btodb(CLBYTES); 1236 } 1237 1238 /* 1239 * Doadump comes here after turning off memory management and 1240 * getting on the dump stack, either when called above, or by 1241 * the auto-restart code. 1242 */ 1243 dumpsys() 1244 { 1245 int error; 1246 1247 msgbufmapped = 0; 1248 if (dumpdev == NODEV) 1249 return; 1250 /* 1251 * For dumps during autoconfiguration, 1252 * if dump device has already configured... 1253 */ 1254 if (dumpsize == 0) 1255 dumpconf(); 1256 if (dumplo < 0) 1257 return; 1258 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 1259 printf("dump "); 1260 switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 1261 1262 case ENXIO: 1263 printf("device bad\n"); 1264 break; 1265 1266 case EFAULT: 1267 printf("device not ready\n"); 1268 break; 1269 1270 case EINVAL: 1271 printf("area improper\n"); 1272 break; 1273 1274 case EIO: 1275 printf("i/o error\n"); 1276 break; 1277 1278 default: 1279 printf("error %d\n", error); 1280 break; 1281 1282 case 0: 1283 printf("succeeded\n"); 1284 } 1285 } 1286 1287 /* 1288 * Return the best possible estimate of the time in the timeval 1289 * to which tvp points. Unfortunately, we can't read the hardware registers. 1290 * We guarantee that the time will be greater than the value obtained by a 1291 * previous call. 1292 */ 1293 void 1294 microtime(tvp) 1295 struct timeval *tvp; 1296 { 1297 int s = splclock(); 1298 static struct timeval lasttime; 1299 1300 *tvp = time; 1301 #ifdef notdef 1302 tvp->tv_usec += clkread(); 1303 while (tvp->tv_usec > 1000000) { 1304 tvp->tv_sec++; 1305 tvp->tv_usec -= 1000000; 1306 } 1307 #endif 1308 if (tvp->tv_sec == lasttime.tv_sec && 1309 tvp->tv_usec <= lasttime.tv_usec && 1310 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 1311 tvp->tv_sec++; 1312 tvp->tv_usec -= 1000000; 1313 } 1314 lasttime = *tvp; 1315 splx(s); 1316 } 1317 1318 initcpu() 1319 { 1320 register volatile struct chiptime *c; 1321 int i; 1322 1323 /* disable clock interrupts (until startrtclock()) */ 1324 c = Mach_clock_addr; 1325 c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT; 1326 i = c->regc; 1327 spl0(); /* safe to turn interrupts on now */ 1328 return (i); 1329 } 1330 1331 /* 1332 * Convert an ASCII string into an integer. 1333 */ 1334 int 1335 atoi(s) 1336 char *s; 1337 { 1338 int c; 1339 unsigned base = 10, d; 1340 int neg = 0, val = 0; 1341 1342 if (s == 0 || (c = *s++) == 0) 1343 goto out; 1344 1345 /* skip spaces if any */ 1346 while (c == ' ' || c == '\t') 1347 c = *s++; 1348 1349 /* parse sign, allow more than one (compat) */ 1350 while (c == '-') { 1351 neg = !neg; 1352 c = *s++; 1353 } 1354 1355 /* parse base specification, if any */ 1356 if (c == '0') { 1357 c = *s++; 1358 switch (c) { 1359 case 'X': 1360 case 'x': 1361 base = 16; 1362 break; 1363 case 'B': 1364 case 'b': 1365 base = 2; 1366 break; 1367 default: 1368 base = 8; 1369 } 1370 } 1371 1372 /* parse number proper */ 1373 for (;;) { 1374 if (c >= '0' && c <= '9') 1375 d = c - '0'; 1376 else if (c >= 'a' && c <= 'z') 1377 d = c - 'a' + 10; 1378 else if (c >= 'A' && c <= 'Z') 1379 d = c - 'A' + 10; 1380 else 1381 break; 1382 val *= base; 1383 val += d; 1384 c = *s++; 1385 } 1386 if (neg) 1387 val = -val; 1388 out: 1389 return val; 1390 } 1391 1392 /* 1393 * Fill in the pmax addresses by hand. 1394 */ 1395 static struct pmax_address { 1396 char *pmax_name; 1397 char *pmax_addr; 1398 int pmax_pri; 1399 } pmax_addresses[] = { 1400 { "pm", (char *)MACH_PHYS_TO_CACHED(KN01_PHYS_FBUF_START), 3 }, 1401 { "dc", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_DZ), 2 }, 1402 { "le", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_LANCE), 1 }, 1403 { "sii",(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_SII), 0 }, 1404 { (char *)0, }, 1405 }; 1406 1407 void 1408 pmax_slot_hand_fill() 1409 { 1410 register struct pmax_ctlr *cp; 1411 register struct driver *drp; 1412 register struct pmax_address *pmap; 1413 1414 /* 1415 * Find the device driver entry and fill in the address. 1416 */ 1417 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) { 1418 for (pmap = pmax_addresses; pmap->pmax_name; pmap++) { 1419 if (strcmp(drp->d_name, pmap->pmax_name)) 1420 continue; 1421 if (cp->pmax_addr == (char *)QUES) { 1422 cp->pmax_addr = pmap->pmax_addr; 1423 cp->pmax_pri = pmap->pmax_pri; 1424 continue; 1425 } 1426 } 1427 } 1428 } 1429 1430 #ifdef DS5000 1431 /* 1432 * Mach Operating System 1433 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 1434 * All Rights Reserved. 1435 * 1436 * Permission to use, copy, modify and distribute this software and its 1437 * documentation is hereby granted, provided that both the copyright 1438 * notice and this permission notice appear in all copies of the 1439 * software, derivative works or modified versions, and any portions 1440 * thereof, and that both notices appear in supporting documentation. 1441 * 1442 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 1443 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 1444 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1445 * 1446 * Carnegie Mellon requests users of this software to return to 1447 * 1448 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 1449 * School of Computer Science 1450 * Carnegie Mellon University 1451 * Pittsburgh PA 15213-3890 1452 * 1453 * any improvements or extensions that they make and grant Carnegie the 1454 * rights to redistribute these changes. 1455 */ 1456 1457 1458 /* 1459 * Driver map: associates a device driver to an option type. 1460 * Drivers name are (arbitrarily) defined in each driver and 1461 * used in the various config tables. 1462 */ 1463 struct drivers_map { 1464 char module_name[TC_ROM_LLEN]; /* from ROM, literally! */ 1465 char *driver_name; /* in bus_??_init[] tables */ 1466 } tc_drivers_map[] = { 1467 { "KN02 ", "dc"}, /* (*) 3max system board (with DC) */ 1468 { "PMAD-AA ", "le"}, /* Ether */ 1469 { "PMAZ-AA ", "asc"}, /* SCSI */ 1470 { "PMAG-AA ", "mfb"}, /* Mono Frame Buffer */ 1471 { "PMAG-BA ", "cfb"}, /* Color Frame Buffer */ 1472 { "PMAGB-BA", "sfb"}, /* Smart Frame Buffer */ 1473 { "PMAG-CA ", "ga"}, /* 2D graphic board */ 1474 { "PMAG-DA ", "gq"}, /* 3D graphic board (LM) */ 1475 { "PMAG-FA ", "gq"}, /* 3D graphic board (HE) */ 1476 { "PMAG-DV ", "xcfb"}, /* (*) maxine Color Frame Buffer */ 1477 { "Z8530 ", "scc"}, /* (*) 3min/maxine serial lines */ 1478 { "ASIC ", "asic"}, /* (*) 3min/maxine DMA controller */ 1479 { "XINE-FDC", "fdc"}, /* (*) maxine floppy controller */ 1480 { "DTOP ", "dtop"}, /* (*) maxine desktop bus */ 1481 { "AMD79c30", "isdn"}, /* (*) maxine ISDN chip */ 1482 { "XINE-FRC", "frc"}, /* (*) maxine free-running counter */ 1483 { "PMAF-AA ", "fza"}, /* slow FDDI */ 1484 { "T3PKT ", "tt"}, /* DECWRL turbochannel T3 */ 1485 { "T1D4PKT ", "ds"}, /* DECWRL turbochannel T1 */ 1486 { "FORE_ATM", "fa"}, /* Fore t??-100 ATM */ 1487 { "LoFi ", "lofi"}, /* DEC audio board */ 1488 { "AV01A-AA", "lofi"}, /* DEC audio board */ 1489 { "AV01B-AA", "lofi"}, /* DEC audio board */ 1490 { "", 0} /* list end */ 1491 }; 1492 1493 /* 1494 * Identify an option on the TC. Looks at the mandatory 1495 * info in the option's ROM and checks it. 1496 */ 1497 #ifdef DEBUG 1498 int tc_verbose = 0; 1499 #endif 1500 1501 static int 1502 tc_identify_option(addr, slot, complain) 1503 tc_rommap_t *addr; 1504 tc_option_t *slot; 1505 int complain; 1506 { 1507 register int i; 1508 unsigned char width; 1509 char firmwr[TC_ROM_LLEN+1], vendor[TC_ROM_LLEN+1], 1510 module[TC_ROM_LLEN+1], host_type[TC_ROM_SLEN+1]; 1511 1512 /* 1513 * We do not really use the 'width' info, but take advantage 1514 * of the restriction that the spec impose on the portion 1515 * of the ROM that maps between +0x3e0 and +0x470, which 1516 * is the only piece we need to look at. 1517 */ 1518 width = addr->rom_width.value; 1519 switch (width) { 1520 case 1: 1521 case 2: 1522 case 4: 1523 break; 1524 1525 default: 1526 #ifdef DEBUG 1527 if (tc_verbose && complain) 1528 printf("%s (x%x) at x%x\n", "Invalid ROM width", 1529 width, addr); 1530 #endif 1531 return (0); 1532 } 1533 1534 if (addr->rom_stride.value != 4) { 1535 #ifdef DEBUG 1536 if (tc_verbose && complain) 1537 printf("%s (x%x) at x%x\n", "Invalid ROM stride", 1538 addr->rom_stride.value, addr); 1539 #endif 1540 return (0); 1541 } 1542 1543 if ((addr->test_data[0] != 0x55) || 1544 (addr->test_data[4] != 0x00) || 1545 (addr->test_data[8] != 0xaa) || 1546 (addr->test_data[12] != 0xff)) { 1547 #ifdef DEBUG 1548 if (tc_verbose && complain) 1549 printf("%s x%x\n", "Test pattern failed, option at", 1550 addr); 1551 #endif 1552 return (0); 1553 } 1554 1555 for (i = 0; i < TC_ROM_LLEN; i++) { 1556 firmwr[i] = addr->firmware_rev[i].value; 1557 vendor[i] = addr->vendor_name[i].value; 1558 module[i] = addr->module_name[i].value; 1559 if (i >= TC_ROM_SLEN) 1560 continue; 1561 host_type[i] = addr->host_firmware_type[i].value; 1562 } 1563 firmwr[TC_ROM_LLEN] = vendor[TC_ROM_LLEN] = 1564 module[TC_ROM_LLEN] = host_type[TC_ROM_SLEN] = '\0'; 1565 1566 #ifdef DEBUG 1567 if (tc_verbose) 1568 printf("%s %s '%s' at 0x%x\n %s %s %s '%s'\n %s %d %s %d %s\n", 1569 "Found a", vendor, module, addr, 1570 "Firmware rev.", firmwr, 1571 "diagnostics for a", host_type, 1572 "ROM size is", addr->rom_size.value << 3, 1573 "Kbytes, uses", addr->slot_size.value, "TC slot(s)"); 1574 #endif 1575 1576 bcopy(module, slot->module_name, TC_ROM_LLEN); 1577 bcopy(vendor, slot->module_id, TC_ROM_LLEN); 1578 bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN); 1579 slot->slot_size = addr->slot_size.value; 1580 slot->rom_width = width; 1581 1582 return (1); 1583 } 1584 1585 /* 1586 * TURBOchannel autoconf procedure. Finds in one sweep what is 1587 * hanging on the bus and fills in the tc_slot_info array. 1588 * This is only the first part of the autoconf scheme, at this 1589 * time we are basically only looking for a graphics board to 1590 * use as system console (all workstations). 1591 */ 1592 1593 void 1594 tc_find_all_options() 1595 { 1596 register int i; 1597 u_long addr; 1598 int found; 1599 register tc_option_t *sl; 1600 struct drivers_map *map; 1601 register struct pmax_ctlr *cp; 1602 register struct driver *drp; 1603 1604 /* 1605 * Take a look at the bus 1606 */ 1607 bzero(tc_slot_info, sizeof(tc_slot_info)); 1608 for (i = tc_max_slot; i >= tc_min_slot;) { 1609 addr = MACH_PHYS_TO_UNCACHED(tc_slot_phys_base[i]); 1610 found = tc_probe_slot(addr, &tc_slot_info[i]); 1611 1612 if (found) { 1613 /* 1614 * Found a slot, make a note of it 1615 */ 1616 tc_slot_info[i].present = 1; 1617 tc_slot_info[i].k1seg_address = addr; 1618 } 1619 1620 i -= tc_slot_info[i].slot_size; 1621 } 1622 1623 /* 1624 * Some slots (e.g. the system slot on 3max) might require 1625 * hand-filling. If so, do it now. 1626 */ 1627 if (tc_slot_hand_fill) 1628 (*tc_slot_hand_fill) (tc_slot_info); 1629 1630 /* 1631 * Now for each alive slot see if we have a device driver that 1632 * handles it. This is done in "priority order", meaning that 1633 * always present devices are at higher slot numbers on all 1634 * current TC machines, and option slots are at lowest numbers. 1635 */ 1636 for (i = TC_MAX_LOGICAL_SLOTS - 1; i >= 0; i--) { 1637 sl = &tc_slot_info[i]; 1638 if (!sl->present) 1639 continue; 1640 found = FALSE; 1641 for (map = tc_drivers_map; map->driver_name; map++) { 1642 if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN)) 1643 continue; 1644 sl->driver_name = map->driver_name; 1645 found = TRUE; 1646 break; 1647 } 1648 if (!found) { 1649 printf("%s %s %s\n", 1650 "Cannot associate a device driver to", 1651 sl->module_name, ". Will (try to) ignore it."); 1652 sl->present = 0; 1653 continue; 1654 } 1655 1656 /* 1657 * Find the device driver entry and fill in the address. 1658 */ 1659 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) { 1660 if (strcmp(drp->d_name, map->driver_name)) 1661 continue; 1662 if (cp->pmax_alive) 1663 continue; 1664 if (cp->pmax_addr == (char *)QUES) { 1665 cp->pmax_addr = (char *)sl->k1seg_address; 1666 cp->pmax_pri = i; 1667 /* 1668 * Only enable interrupts if there is an 1669 * interrupt handler for it. (e.g., PMAG-BA 1670 * can't disable the vertical retrace interrupt 1671 * and we might want to ignore it). 1672 */ 1673 if (drp->d_intr) 1674 (*tc_enable_interrupt)(i, 1); 1675 cp->pmax_alive = 1; 1676 break; 1677 } 1678 if (cp->pmax_addr != (char *)sl->k1seg_address) { 1679 cp->pmax_addr = (char *)QUES; 1680 printf("%s: device not at configued address (expected at %x, found at %x)\n", 1681 drp->d_name, 1682 cp->pmax_addr, sl->k1seg_address); 1683 } 1684 } 1685 } 1686 } 1687 1688 /* 1689 * Probe a slot in the TURBOchannel. Return TRUE if a valid option 1690 * is present, FALSE otherwise. A side-effect is to fill the slot 1691 * descriptor with the size of the option, whether it is 1692 * recognized or not. 1693 */ 1694 int 1695 tc_probe_slot(addr, slot) 1696 caddr_t addr; 1697 tc_option_t *slot; 1698 { 1699 int i; 1700 static unsigned tc_offset_rom[] = { 1701 TC_OFF_PROTO_ROM, TC_OFF_ROM 1702 }; 1703 #define TC_N_OFFSETS sizeof(tc_offset_rom)/sizeof(unsigned) 1704 1705 slot->slot_size = 1; 1706 1707 for (i = 0; i < TC_N_OFFSETS; i++) { 1708 if (badaddr(addr + tc_offset_rom[i], 4)) 1709 continue; 1710 /* complain only on last chance */ 1711 if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]), 1712 slot, i == (TC_N_OFFSETS-1))) 1713 return (1); 1714 } 1715 return (0); 1716 #undef TC_N_OFFSETS 1717 } 1718 1719 /* 1720 * Enable/Disable interrupts for a TURBOchannel slot. 1721 */ 1722 void 1723 kn02_enable_intr(slotno, on) 1724 register int slotno; 1725 int on; 1726 { 1727 register volatile int *p_csr = 1728 (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR); 1729 int csr; 1730 int s; 1731 1732 slotno = 1 << (slotno + KN02_CSR_IOINTEN_SHIFT); 1733 s = Mach_spl0(); 1734 csr = *p_csr & ~(KN02_CSR_WRESERVED | 0xFF); 1735 if (on) 1736 *p_csr = csr | slotno; 1737 else 1738 *p_csr = csr & ~slotno; 1739 splx(s); 1740 } 1741 1742 /* 1743 * Object: 1744 * kmin_enable_intr EXPORTED function 1745 * 1746 * Enable/Disable interrupts from a TURBOchannel slot. 1747 * 1748 * We pretend we actually have 8 slots even if we really have 1749 * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to 1750 * slots 3-7 (see kmin_slot_hand_fill). 1751 */ 1752 void 1753 kmin_enable_intr(slotno, on) 1754 register unsigned int slotno; 1755 int on; 1756 { 1757 register unsigned mask; 1758 1759 switch (slotno) { 1760 case 0: 1761 case 1: 1762 case 2: 1763 return; 1764 case KMIN_SCSI_SLOT: 1765 mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD | 1766 KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E); 1767 break; 1768 case KMIN_LANCE_SLOT: 1769 mask = KMIN_INTR_LANCE; 1770 break; 1771 case KMIN_SCC0_SLOT: 1772 mask = KMIN_INTR_SCC_0; 1773 break; 1774 case KMIN_SCC1_SLOT: 1775 mask = KMIN_INTR_SCC_1; 1776 break; 1777 case KMIN_ASIC_SLOT: 1778 mask = KMIN_INTR_ASIC; 1779 break; 1780 default: 1781 return; 1782 } 1783 if (on) 1784 kmin_tc3_imask |= mask; 1785 else 1786 kmin_tc3_imask &= ~mask; 1787 } 1788 1789 /* 1790 * Object: 1791 * xine_enable_intr EXPORTED function 1792 * 1793 * Enable/Disable interrupts from a TURBOchannel slot. 1794 * 1795 * We pretend we actually have 11 slots even if we really have 1796 * only 3: TCslots 0-1 maps to slots 0-1, TCslot 2 is used for 1797 * the system (TCslot3), TCslot3 maps to slots 3-10 1798 * (see xine_slot_hand_fill). 1799 * Note that all these interrupts come in via the IMR. 1800 */ 1801 void 1802 xine_enable_intr(slotno, on) 1803 register unsigned int slotno; 1804 int on; 1805 { 1806 register unsigned mask; 1807 1808 switch (slotno) { 1809 case 0: /* a real slot, but */ 1810 mask = XINE_INTR_TC_0; 1811 break; 1812 case 1: /* a real slot, but */ 1813 mask = XINE_INTR_TC_1; 1814 break; 1815 case XINE_FLOPPY_SLOT: 1816 mask = XINE_INTR_FLOPPY; 1817 break; 1818 case XINE_SCSI_SLOT: 1819 mask = (XINE_INTR_SCSI | XINE_INTR_SCSI_PTR_LOAD | 1820 XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E); 1821 break; 1822 case XINE_LANCE_SLOT: 1823 mask = XINE_INTR_LANCE; 1824 break; 1825 case XINE_SCC0_SLOT: 1826 mask = XINE_INTR_SCC_0; 1827 break; 1828 case XINE_DTOP_SLOT: 1829 mask = XINE_INTR_DTOP_RX; 1830 break; 1831 case XINE_ISDN_SLOT: 1832 mask = XINE_INTR_ISDN; 1833 break; 1834 case XINE_ASIC_SLOT: 1835 mask = XINE_INTR_ASIC; 1836 break; 1837 default: 1838 return;/* ignore */ 1839 } 1840 if (on) 1841 xine_tc3_imask |= mask; 1842 else 1843 xine_tc3_imask &= ~mask; 1844 } 1845 1846 #ifdef DS5000_240 1847 /* 1848 * UNTESTED!! 1849 * Object: 1850 * kn03_enable_intr EXPORTED function 1851 * 1852 * Enable/Disable interrupts from a TURBOchannel slot. 1853 * 1854 * We pretend we actually have 8 slots even if we really have 1855 * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to 1856 * slots 3-7 (see kn03_slot_hand_fill). 1857 */ 1858 void 1859 kn03_enable_intr(slotno, on) 1860 register unsigned int slotno; 1861 int on; 1862 { 1863 register unsigned mask; 1864 1865 switch (slotno) { 1866 case 0: 1867 mask = KN03_INTR_TC_0; 1868 break; 1869 case 1: 1870 mask = KN03_INTR_TC_1; 1871 break; 1872 case 2: 1873 mask = KN03_INTR_TC_2; 1874 break; 1875 case KN03_SCSI_SLOT: 1876 mask = (KN03_INTR_SCSI | KN03_INTR_SCSI_PTR_LOAD | 1877 KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E); 1878 break; 1879 case KN03_LANCE_SLOT: 1880 mask = KN03_INTR_LANCE; 1881 break; 1882 case KN03_SCC0_SLOT: 1883 mask = KN03_INTR_SCC_0; 1884 break; 1885 case KN03_SCC1_SLOT: 1886 mask = KN03_INTR_SCC_1; 1887 break; 1888 case KN03_ASIC_SLOT: 1889 mask = KN03_INTR_ASIC; 1890 break; 1891 default: 1892 return; 1893 } 1894 if (on) 1895 kn03_tc3_imask |= mask; 1896 else 1897 kn03_tc3_imask &= ~mask; 1898 } 1899 #endif /* DS5000_240 */ 1900 1901 /* 1902 * Object: 1903 * kn02_slot_hand_fill EXPORTED function 1904 * 1905 * Fill in by hand the info for TC slots that are non-standard. 1906 * This is basically just the system slot on a 3max, it does not 1907 * look to me like it follows the TC rules although some of the 1908 * required info is indeed there. 1909 * 1910 */ 1911 void 1912 kn02_slot_hand_fill(slot) 1913 tc_option_t *slot; 1914 { 1915 slot[7].present = 1; 1916 slot[7].slot_size = 1; 1917 slot[7].rom_width = 1; 1918 #if unsafe 1919 bcopy(0xbffc0410, slot[7].module_name, TC_ROM_LLEN+1); 1920 #endif 1921 bcopy("KN02 ", slot[7].module_name, TC_ROM_LLEN+1); 1922 bcopy("DEC xxxx", slot[7].module_id, TC_ROM_LLEN+1); 1923 slot[7].k1seg_address = MACH_PHYS_TO_UNCACHED(KN02_SYS_DZ); 1924 } 1925 1926 /* 1927 * Object: 1928 * kmin_slot_hand_fill EXPORTED function 1929 * 1930 * Fill in by hand the info for TC slots that are non-standard. 1931 * This is the system slot on a 3min, which we think of as a 1932 * set of non-regular size TC slots. 1933 * 1934 */ 1935 void 1936 kmin_slot_hand_fill(slot) 1937 tc_option_t *slot; 1938 { 1939 register int i; 1940 1941 for (i = KMIN_SCSI_SLOT; i < KMIN_ASIC_SLOT+1; i++) { 1942 slot[i].present = 1; 1943 slot[i].slot_size = 1; 1944 slot[i].rom_width = 1; 1945 slot[i].unit = 0; 1946 bcopy("DEC KMIN", slot[i].module_id, TC_ROM_LLEN+1); 1947 } 1948 1949 /* scsi */ 1950 bcopy("PMAZ-AA ", slot[KMIN_SCSI_SLOT].module_name, TC_ROM_LLEN+1); 1951 slot[KMIN_SCSI_SLOT].k1seg_address = 1952 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCSI); 1953 1954 /* lance */ 1955 bcopy("PMAD-AA ", slot[KMIN_LANCE_SLOT].module_name, TC_ROM_LLEN+1); 1956 slot[KMIN_LANCE_SLOT].k1seg_address = 0; 1957 1958 /* scc */ 1959 bcopy("Z8530 ", slot[KMIN_SCC0_SLOT].module_name, TC_ROM_LLEN+1); 1960 slot[KMIN_SCC0_SLOT].k1seg_address = 1961 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_0); 1962 1963 slot[KMIN_SCC1_SLOT].unit = 1; 1964 bcopy("Z8530 ", slot[KMIN_SCC1_SLOT].module_name, TC_ROM_LLEN+1); 1965 slot[KMIN_SCC1_SLOT].k1seg_address = 1966 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_1); 1967 1968 /* asic */ 1969 bcopy("ASIC ", slot[KMIN_ASIC_SLOT].module_name, TC_ROM_LLEN+1); 1970 slot[KMIN_ASIC_SLOT].k1seg_address = 1971 MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC); 1972 asic_init(0); 1973 } 1974 1975 /* 1976 * Object: 1977 * xine_slot_hand_fill EXPORTED function 1978 * 1979 * Fill in by hand the info for TC slots that are non-standard. 1980 * This is the system slot on a 3min, which we think of as a 1981 * set of non-regular size TC slots. 1982 * 1983 */ 1984 void 1985 xine_slot_hand_fill(slot) 1986 tc_option_t *slot; 1987 { 1988 register int i; 1989 1990 for (i = XINE_FLOPPY_SLOT; i < XINE_FRC_SLOT+1; i++) { 1991 slot[i].present = 1; 1992 slot[i].slot_size = 1; 1993 slot[i].rom_width = 1; 1994 slot[i].unit = 0; 1995 bcopy("DEC XINE", slot[i].module_id, TC_ROM_LLEN+1); 1996 } 1997 1998 /* floppy */ 1999 bcopy("XINE-FDC", slot[XINE_FLOPPY_SLOT].module_name, TC_ROM_LLEN+1); 2000 slot[XINE_FLOPPY_SLOT].k1seg_address = 2001 MACH_PHYS_TO_UNCACHED(XINE_SYS_FLOPPY); 2002 2003 /* scsi */ 2004 bcopy("PMAZ-AA ", slot[XINE_SCSI_SLOT].module_name, TC_ROM_LLEN+1); 2005 slot[XINE_SCSI_SLOT].k1seg_address = 2006 MACH_PHYS_TO_UNCACHED(XINE_SYS_SCSI); 2007 2008 /* lance */ 2009 bcopy("PMAD-AA ", slot[XINE_LANCE_SLOT].module_name, TC_ROM_LLEN+1); 2010 slot[XINE_LANCE_SLOT].k1seg_address = 2011 MACH_PHYS_TO_UNCACHED(XINE_SYS_LANCE); 2012 2013 /* scc */ 2014 bcopy("Z8530 ", slot[XINE_SCC0_SLOT].module_name, TC_ROM_LLEN+1); 2015 slot[XINE_SCC0_SLOT].k1seg_address = 2016 MACH_PHYS_TO_UNCACHED(XINE_SYS_SCC_0); 2017 2018 /* Desktop */ 2019 bcopy("DTOP ", slot[XINE_DTOP_SLOT].module_name, TC_ROM_LLEN+1); 2020 slot[XINE_DTOP_SLOT].k1seg_address = 2021 MACH_PHYS_TO_UNCACHED(XINE_SYS_DTOP+0x20000); /* why? */ 2022 2023 /* ISDN */ 2024 bcopy("AMD79c30", slot[XINE_ISDN_SLOT].module_name, TC_ROM_LLEN+1); 2025 slot[XINE_ISDN_SLOT].k1seg_address = 2026 MACH_PHYS_TO_UNCACHED(XINE_SYS_ISDN); 2027 2028 /* Video */ 2029 bcopy("PMAG-DV ", slot[XINE_CFB_SLOT].module_name, TC_ROM_LLEN+1); 2030 slot[XINE_CFB_SLOT].k1seg_address = 2031 MACH_PHYS_TO_CACHED(XINE_PHYS_CFB_START); 2032 2033 /* asic */ 2034 bcopy("ASIC ", slot[XINE_ASIC_SLOT].module_name, TC_ROM_LLEN+1); 2035 slot[XINE_ASIC_SLOT].k1seg_address = 2036 MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC); 2037 2038 /* free-running counter (high resolution mapped time) */ 2039 bcopy("XINE-FRC", slot[XINE_FRC_SLOT].module_name, TC_ROM_LLEN+1); 2040 slot[XINE_FRC_SLOT].k1seg_address = 2041 MACH_PHYS_TO_UNCACHED(XINE_REG_FCTR); 2042 asic_init(1); 2043 } 2044 2045 #ifdef DS5000_240 2046 /* 2047 * UNTESTED!! 2048 * Object: 2049 * kn03_slot_hand_fill EXPORTED function 2050 * 2051 * Fill in by hand the info for TC slots that are non-standard. 2052 * This is the system slot on a 3max+, which we think of as a 2053 * set of non-regular size TC slots. 2054 * 2055 */ 2056 void 2057 kn03_slot_hand_fill(slot) 2058 tc_option_t *slot; 2059 { 2060 register int i; 2061 2062 for (i = KN03_SCSI_SLOT; i < KN03_ASIC_SLOT+1; i++) { 2063 slot[i].present = 1; 2064 slot[i].slot_size = 1; 2065 slot[i].rom_width = 1; 2066 slot[i].unit = 0; 2067 bcopy("DEC KN03", slot[i].module_id, TC_ROM_LLEN+1); 2068 } 2069 2070 /* scsi */ 2071 bcopy("PMAZ-AA ", slot[KN03_SCSI_SLOT].module_name, TC_ROM_LLEN+1); 2072 slot[KN03_SCSI_SLOT].k1seg_address = 2073 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCSI); 2074 2075 /* lance */ 2076 bcopy("PMAD-AA ", slot[KN03_LANCE_SLOT].module_name, TC_ROM_LLEN+1); 2077 slot[KN03_LANCE_SLOT].k1seg_address = 0; 2078 2079 /* scc */ 2080 bcopy("Z8530 ", slot[KN03_SCC0_SLOT].module_name, TC_ROM_LLEN+1); 2081 slot[KN03_SCC0_SLOT].k1seg_address = 2082 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_0); 2083 2084 slot[KN03_SCC1_SLOT].unit = 1; 2085 bcopy("Z8530 ", slot[KN03_SCC1_SLOT].module_name, TC_ROM_LLEN+1); 2086 slot[KN03_SCC1_SLOT].k1seg_address = 2087 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_1); 2088 2089 /* asic */ 2090 bcopy("ASIC ", slot[KN03_ASIC_SLOT].module_name, TC_ROM_LLEN+1); 2091 slot[KN03_ASIC_SLOT].k1seg_address = 2092 MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC); 2093 asic_init(0); 2094 } 2095 #endif /* DS5000_240 */ 2096 2097 /* 2098 * Initialize the I/O asic 2099 */ 2100 static void 2101 asic_init(isa_maxine) 2102 int isa_maxine; 2103 { 2104 volatile u_int *decoder; 2105 2106 /* These are common between 3min and maxine */ 2107 decoder = (volatile u_int *)ASIC_REG_LANCE_DECODE(asic_base); 2108 *decoder = KMIN_LANCE_CONFIG; 2109 } 2110 #endif /* DS5000 */ 2111