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