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