/* * uvaxIII_conf() is called by cpu_attach to do the cpu_specific setup. */ void uvaxIII_conf() { int syssub = GETSYSSUBT(vax_siedata); /* * MicroVAX III: We map in memory error registers, * cache control registers, SSC registers, * interprocessor registers and cache diag space. */ ka650merr_ptr = (void *)vax_map_physmem(KA650_MERR, 1); ka650cbd_ptr = (void *)vax_map_physmem(KA650_CBD, 1); ka650ssc_ptr = (void *)vax_map_physmem(KA650_SSC, 3); ka650ipcr_ptr = (void *)vax_map_physmem(KA650_IPCR, 1); KA650_CACHE_ptr = (void *)vax_map_physmem(KA650_CACHE, (KA650_CACHESIZE/VAX_NBPG)); printf("cpu: KA6%d%d, CVAX microcode rev %d Firmware rev %d\n", syssub == VAX_SIE_KA640 ? 4 : 5, syssub == VAX_SIE_KA655 ? 5 : 0, (vax_cpudata & 0xff), GETFRMREV(vax_siedata)); ka650setcache(CACHEON); if (ctob(physmem) > ka650merr_ptr->merr_qbmbr) { printf("physmem(0x%x) > qbmbr(0x%x)\n", ctob(physmem), (int)ka650merr_ptr->merr_qbmbr); panic("qbus map unprotected"); } if (mfpr(PR_TODR) == 0) mtpr(1, PR_TODR); }
void ka53_conf() { char *cpuname; /* This initialises ISP, avoiding interrupt exceptions */ {volatile int *hej = (void *)mfpr(PR_ISP); *hej = *hej; hej[-1] = hej[-1];} /* This vector (qbus related?) comes out of nowhere, ignore it for now */ scb_vecalloc(0x0, (void *)nullop, NULL, SCB_ISTACK, NULL); cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1); switch((vax_siedata >> 8) & 0xFF) { case VAX_STYP_50: cpuname = "KA50"; break; case VAX_STYP_51: cpuname = "KA51"; break; case VAX_STYP_52: cpuname = "KA52"; break; case VAX_STYP_53: cpuname = "KA53"; break; default: cpuname = "unknown NVAX"; } printf("cpu0: %s, ucode rev %d\n", cpuname, vax_cpudata & 0xff); }
/* * iinit is called once (from main) * very early in initialization. * It reads the root's super block * and initializes the current date * from the last modified date. * * panic: iinit -- cannot read the super * block. Usually because of an IO error. */ iinit() { register struct buf *cp, *bp; register struct filsys *fp; register unsigned i , j ; (*bdevsw[major(rootdev)].d_open)(rootdev, 1); bp = bread(rootdev, SUPERB); cp = geteblk(); if(u.u_error) panic("iinit"); bcopy(bp->b_un.b_addr, cp->b_un.b_addr, sizeof(struct filsys)); brelse(bp); mount[0].m_bufp = cp; mount[0].m_dev = rootdev; fp = cp->b_un.b_filsys; fp->s_flock = 0; fp->s_ilock = 0; fp->s_ronly = 0; /* on boot, read VAX TODR register (GMT 10 ms. * clicks into current year) and set software time * in 'int time' (GMT seconds since year YRREF) */ for (i = 0 , j = YRREF ; j < YRCURR ; j++) i += (SECYR + (j%4?0:SECDAY)) ; time = udiv(mfpr(TODR),100) + i ; }
/* * Stray interrupt handler. * This function must _not_ save any registers (in the reg save mask). */ void scb_stray(void *arg) { static int vector, ipl; ipl = mfpr(PR_IPL); vector = (int) arg; /* printf("stray interrupt: vector 0x%x, ipl %d\n", vector, ipl); */ kprintf("stray interrupt: vector %d, ipl %d\n", vector, ipl); }
void ka750_conf() { printf("cpu0: KA750, hardware rev %d, ucode rev %d, ", V750HARDW(vax_cpudata), V750UCODE(vax_cpudata)); if (mfpr(PR_ACCS) & 255) { printf("FPA present, enabling.\n"); mtpr(0x8000, PR_ACCS); } else printf("no FPA\n"); if (mfpr(PR_TODR) == 0) { /* Check for failing battery */ mtpr(1, PR_TODR); printf("WARNING: TODR battery broken\n"); } /* Call ctuattach() here so it can setup its vectors. */ ctuattach(); }
void ka53_conf(void) { /* Don't ask why, but we seem to need this... */ volatile int *hej = (void *)mfpr(PR_ISP); *hej = *hej; hej[-1] = hej[-1]; cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1); }
/* * pr_putchar() using MTPR */ void pr_putchar(int c) { int timeout = 1<<15; /* don't hang the machine! */ while (mfpr(PR_RXCS) & GC_DON) { if ((mfpr(PR_RXDB) & 0x7f) == 19) { while (1) { while ((mfpr(PR_RXCS) & GC_DON) == 0) ; if ((mfpr(PR_RXDB) & 0x7f) == 17) break; } } } while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ if (--timeout < 0) break; mtpr(c, PR_TXDB); /* xmit character */ }
int ka730_mchk(void *cmcf) { register struct mc730frame *mcf = (struct mc730frame *)cmcf; register int type = mcf->mc3_summary; printf("machine check %x: %s\n", type, type < NMC730 ? mc730[type] : "???"); printf("\tparams %x %x pc %x psl %x mcesr %x\n", mcf->mc3_parm[0], mcf->mc3_parm[1], mcf->mc3_pc, mcf->mc3_psl, mfpr(PR_MCESR)); mtpr(0xf, PR_MCESR); return (MCHK_PANIC); }
void ka680_conf() { char *cpuname; /* Don't ask why, but we seem to need this... */ volatile int *hej = (void *)mfpr(PR_ISP); *hej = *hej; hej[-1] = hej[-1]; cpmbx = (struct cpmbx *)vax_map_physmem(0x20140400, 1); switch(vax_boardtype) { case VAX_BTYP_1301: switch((vax_siedata & 0xff00) >> 8) { case VAX_STYP_675: cpuname = "KA675"; break; case VAX_STYP_680: cpuname = "KA680"; break; case VAX_STYP_690: cpuname = "KA690"; break; default: cpuname = "unknown NVAX 1301"; } break; case VAX_BTYP_1305: switch((vax_siedata & 0xff00) >> 8) { case VAX_STYP_681: cpuname = "KA681"; break; case VAX_STYP_691: cpuname = "KA691"; break; case VAX_STYP_694: if (vax_cpudata & 0x1000) cpuname = "KA694"; else cpuname = "KA692"; break; default: cpuname = "unknown NVAX 1305"; } } printf("cpu0: %s, ucode rev %d\n", cpuname, vax_cpudata & 0xff); }
/* * Stray interrupt handler. * This function must _not_ save any registers (in the reg save mask). */ void scb_stray(void *arg) { gotintr = 1; vector = ((int) arg) & ~3; ipl = mfpr(PR_IPL); if (cold == 0) { printf("stray interrupt: vector 0x%x, ipl %d\n", vector, ipl); } else if (dep_call->cpu_flags & CPU_RAISEIPL) { struct icallsframe *icf = (void *) __builtin_frame_address(0); icf->ica_psl = (icf->ica_psl & ~PSL_IPL) | ipl << 16; } mtpr(ipl + 1, PR_IPL); }
/* * Stray interrupt handler. * This function must _not_ save any registers (in the reg save mask). */ void scb_stray(void *arg) { gotintr = 1; vector = ((int) arg) & ~3; ipl = mfpr(PR_IPL); if (cold == 0) printf("stray interrupt: vector %d, ipl %d\n", vector, ipl); else { struct icallsframe *icf = (void *) __builtin_frame_address(0); icf->ica_psl = (icf->ica_psl & ~PSL_IPL) | ipl << 16; } mtpr(ipl + 1, PR_IPL); }
void ka49_conf() { printf("cpu0: KA49\n"); /* Why??? */ { volatile int *hej = (void *)mfpr(PR_ISP); *hej = *hej; hej[-1] = hej[-1];} /* This vector shows up during shutdown, ignore it for now. */ scb_vecalloc(0x0, (void *)nullop, NULL, SCB_ISTACK, NULL); /* * Setup parameters necessary to read time from clock chip. */ clk_adrshift = 1; /* Addressed at long's... */ clk_tweak = 2; /* ...and shift two */ clk_page = (short *)vax_map_physmem(0x25400000, 1); }
void cflstart(void) { struct buf *bp; bp = cfltab.cfl_buf; cfltab.cfl_errcnt = 0; cfltab.cfl_xaddr = (unsigned char *) bp->b_data; cfltab.cfl_active = CFL_START; bp->b_resid = 0; if ((mfpr(PR_TXCS) & GC_RDY) == 0) /* not ready to receive order */ return; cfltab.cfl_active = CFL_SECTOR; mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT, PR_TXDB); #ifdef lint cflintr(); #endif }
/* log CRD errors */ ka860_memerr() { register int reg11; /* known to be r11 below */ int mdecc, mear, mstat1, mstat2, array; /* * Scratchpad registers in the Ebox must be read by * storing their ID number in ESPA and then immediately * reading ESPD's contents with no other intervening * machine instructions! * * The asm's below have a number of constants which * are defined correctly above and in mtpr.h. */ #ifdef lint reg11 = 0; #else asm("mtpr $0x27,$0x4e; mfpr $0x4f,r11"); #endif mdecc = reg11; /* must acknowledge interrupt? */ if (M8600_MEMERR(mdecc)) { asm("mtpr $0x2a,$0x4e; mfpr $0x4f,r11"); mear = reg11; asm("mtpr $0x25,$0x4e; mfpr $0x4f,r11"); mstat1 = reg11; asm("mtpr $0x26,$0x4e; mfpr $0x4f,r11"); mstat2 = reg11; array = M8600_ARRAY(mear); printf("mcr0: ecc error, addr %x (array %d) syn %x\n", M8600_ADDR(mear), array, M8600_SYN(mdecc)); printf("\tMSTAT1 = %b\n\tMSTAT2 = %b\n", mstat1, M8600_MSTAT1_BITS, mstat2, M8600_MSTAT2_BITS); mtpr(EHSR, 0); mtpr(MERG, mfpr(MERG) | M8600_ICRD); } }
void crlstart(void) { struct buf *bp; bp = crltab.crl_buf; crltab.crl_errcnt = 0; crltab.crl_xaddr = (ushort *) bp->b_data; bp->b_resid = 0; if ((mfpr(PR_STXCS) & STXCS_RDY) == 0) /* not ready to receive order */ return; if ((bp->b_flags&(B_READ|B_WRITE)) == B_READ) { crltab.crl_active = CRL_F_READ; mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS); } else { crltab.crl_active = CRL_F_WRITE; mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS); } #ifdef lint crlintr(NULL); #endif }
/* * Try to figure out which type of system this is. */ void findcpu(void) { vax_cpudata = mfpr(PR_SID); vax_cputype = vax_cpudata >> 24; vax_boardtype = vax_cputype << 24; switch (vax_cputype) { case VAX_TYP_780: vax_bustype = VAX_SBIBUS; break; case VAX_TYP_750: vax_bustype = VAX_CMIBUS; break; case VAX_TYP_790: vax_bustype = VAX_ABUS; break; case VAX_TYP_UV2: case VAX_TYP_CVAX: case VAX_TYP_RIGEL: case VAX_TYP_MARIAH: case VAX_TYP_NVAX: case VAX_TYP_SOC: vax_siedata = *(int *)(0x20040004); /* SIE address */ vax_boardtype |= vax_siedata >> 24; switch (vax_boardtype) { case VAX_BTYP_420: /* They are very similar */ case VAX_BTYP_410: case VAX_BTYP_43: case VAX_BTYP_46: case VAX_BTYP_48: case VAX_BTYP_IS1: vax_confdata = *(int *)(0x20020000); vax_bustype = VAX_VSBUS; break; case VAX_BTYP_49: vax_confdata = *(int *)(0x25800000); vax_bustype = VAX_VSBUS; break; case VAX_BTYP_VXT: vax_confdata = *(int *)(0x200c0000); vax_bustype = VAX_VXTBUS; break; case VAX_BTYP_9CC: case VAX_BTYP_9RR: case VAX_BTYP_1202: case VAX_BTYP_1302: vax_bustype = VAX_XMIBUS; break; case VAX_BTYP_60: vax_confdata = ((struct cvax_ssc *)CVAX_SSC)->ssc_terminfo; vax_bustype = VAX_MBUS; break; case VAX_BTYP_630: case VAX_BTYP_650: case VAX_BTYP_660: case VAX_BTYP_670: case VAX_BTYP_1301: case VAX_BTYP_1303: case VAX_BTYP_1305: vax_bustype = VAX_IBUS; break; } break; case VAX_TYP_8SS: vax_boardtype = VAX_BTYP_8000; vax_bustype = VAX_BIBUS; break; case VAX_TYP_8NN: case VAX_TYP_8PS: vax_boardtype = VAX_BTYP_8800; vax_bustype = VAX_NBIBUS; break; default: /* CPU not supported, just give up */ asm("halt"); } }
/* * Start is called from boot; the first routine that is called * in kernel. Kernel stack is setup somewhere in a safe place; * but we need to move it to a better known place. Memory * management is disabled, and no interrupt system is active. */ void start(struct rpb *prpb) { extern void *scratch; mtpr(AST_NO, PR_ASTLVL); /* Turn off ASTs */ findcpu(); /* Set up the CPU identifying variables */ if (vax_confdata & 0x80) strlcpy(cpu_model, "MicroVAX ", sizeof cpu_model); else strlcpy(cpu_model, "VAXstation ", sizeof cpu_model); switch (vax_boardtype) { #if VAX780 case VAX_BTYP_780: dep_call = &ka780_calls; strlcpy(cpu_model,"VAX 11/780", sizeof cpu_model); if (vax_cpudata & 0x100) cpu_model[9] = '5'; break; #endif #if VAX750 case VAX_BTYP_750: dep_call = &ka750_calls; strlcpy(cpu_model, "VAX 11/750", sizeof cpu_model); break; #endif #if VAX8600 case VAX_BTYP_790: dep_call = &ka860_calls; strlcpy(cpu_model,"VAX 8600", sizeof cpu_model); if (vax_cpudata & 0x100) cpu_model[6] = '5'; break; #endif #if VAX410 case VAX_BTYP_420: /* They are very similar */ dep_call = &ka410_calls; strlcat(cpu_model, "3100", sizeof cpu_model); switch ((vax_siedata >> 8) & 0xff) { case 0x00: strlcat(cpu_model, "/m{30,40}", sizeof cpu_model); break; case 0x01: strlcat(cpu_model, "/m{38,48}", sizeof cpu_model); break; case 0x02: strlcat(cpu_model, "/m{10,20}{,e}", sizeof cpu_model); break; } break; case VAX_BTYP_410: dep_call = &ka410_calls; strlcat(cpu_model, "2000", sizeof cpu_model); break; #endif #if VAX43 case VAX_BTYP_43: dep_call = &ka43_calls; strlcat(cpu_model, "3100/m76", sizeof cpu_model); break; #endif #if VAX46 case VAX_BTYP_46: dep_call = &ka46_calls; switch(vax_siedata & 0xff) { case VAX_VTYP_47: strlcpy(cpu_model, "MicroVAX 3100 m80", sizeof cpu_model); break; case VAX_VTYP_46: strlcpy(cpu_model, "VAXstation 4000/60", sizeof cpu_model); break; default: strlcat(cpu_model, " - Unknown Mariah", sizeof cpu_model); } break; #endif #ifdef VXT case VAX_BTYP_VXT: dep_call = &vxt_calls; strlcpy(cpu_model, "VXT2000", sizeof cpu_model); break; #endif #if VAX48 case VAX_BTYP_48: dep_call = &ka48_calls; switch ((vax_siedata >> 8) & 0xff) { case VAX_STYP_45: strlcpy(cpu_model, "MicroVAX 3100/m{30,40}", sizeof cpu_model); break; case VAX_STYP_48: strlcpy(cpu_model, "VAXstation 4000/VLC", sizeof cpu_model); break; default: strlcat(cpu_model, " - Unknown SOC", sizeof cpu_model); } break; #endif #if VAX49 case VAX_BTYP_49: dep_call = &ka49_calls; strlcpy(cpu_model, "VAXstation 4000/90", sizeof cpu_model); break; #endif #if VAX53 case VAX_BTYP_1303: dep_call = &ka53_calls; switch ((vax_siedata >> 8) & 0xff) { case VAX_STYP_50: strlcpy(cpu_model, "MicroVAX 3100 model 85 or 90", sizeof cpu_model); break; case VAX_STYP_51: strlcpy(cpu_model, "MicroVAX 3100 model 90 or 95", sizeof cpu_model); break; case VAX_STYP_52: strlcpy(cpu_model, "VAX 4000 100", sizeof cpu_model); break; case VAX_STYP_53: strlcpy(cpu_model, "VAX 4000 105A", sizeof cpu_model); break; default: strlcpy(cpu_model, "VAX - Unknown Cheetah Class", sizeof cpu_model); } break; #endif #if VAX630 case VAX_BTYP_630: dep_call = &ka630_calls; strlcpy(cpu_model,"MicroVAX II", sizeof cpu_model); break; #endif #if VAX650 case VAX_BTYP_650: dep_call = &ka650_calls; strlcpy(cpu_model,"MicroVAX ", sizeof cpu_model); switch ((vax_siedata >> 8) & 255) { case VAX_SIE_KA640: strlcat(cpu_model, "3300/3400", sizeof cpu_model); break; case VAX_SIE_KA650: strlcat(cpu_model, "3500/3600", sizeof cpu_model); break; case VAX_SIE_KA655: strlcat(cpu_model, "3800/3900", sizeof cpu_model); break; default: strlcat(cpu_model, "III", sizeof cpu_model); break; } break; #endif #if VAX660 case VAX_BTYP_660: dep_call = &ka660_calls; strlcpy(cpu_model,"VAX 4000 200", sizeof cpu_model); break; #endif #if VAX670 case VAX_BTYP_670: dep_call = &ka670_calls; strlcpy(cpu_model,"VAX 4000 300", sizeof cpu_model); break; #endif #if VAX680 case VAX_BTYP_1301: dep_call = &ka680_calls; strlcpy(cpu_model,"VAX 4000 ", sizeof cpu_model); switch ((vax_siedata >> 8) & 0xff) { case VAX_STYP_675: strlcat(cpu_model,"400", sizeof cpu_model); break; case VAX_STYP_680: strlcat(cpu_model,"500", sizeof cpu_model); break; case VAX_STYP_690: strlcat(cpu_model,"600", sizeof cpu_model); break; default: strlcat(cpu_model,"- Unknown Omega Class", sizeof cpu_model); } break; case VAX_BTYP_1305: dep_call = &ka680_calls; strlcpy(cpu_model,"VAX 4000 ", sizeof cpu_model); switch ((vax_siedata >> 8) & 0xff) { case VAX_STYP_681: strlcat(cpu_model,"500A", sizeof cpu_model); break; case VAX_STYP_691: strlcat(cpu_model,"605A", sizeof cpu_model); break; case VAX_STYP_694: if (vax_cpudata & 0x1000) strlcat(cpu_model,"705A", sizeof cpu_model); else strlcat(cpu_model,"700A", sizeof cpu_model); break; default: strlcat(cpu_model,"- Unknown Legacy Class", sizeof cpu_model); } break; #endif #if VAX8200 case VAX_BTYP_8000: mastercpu = mfpr(PR_BINID); dep_call = &ka820_calls; strlcpy(cpu_model, "VAX 8200", sizeof cpu_model); break; #endif default: /* CPU not supported, just give up */ asm("halt"); } /* * Machines older than MicroVAX II have their boot blocks * loaded directly or the boot program loaded from console * media, so we need to figure out their memory size. * This is not easily done on MicroVAXen, so we get it from * VMB instead. * * In post-1.4 a RPB is always provided from the boot blocks. */ #if 1 /* compat with old bootblocks */ if (prpb == 0) { bzero((caddr_t)proc0paddr + REDZONEADDR, sizeof(struct rpb)); prpb = (struct rpb *)(proc0paddr + REDZONEADDR); prpb->pfncnt = avail_end >> VAX_PGSHIFT; prpb->rpb_base = (void *)-1; /* RPB is fake */ } else
void ka53_cache_enable(void) { int start, s**t; /* * Turn caches off. */ mtpr(0, PR_ICSR); mtpr(0, PR_PCCTL); mtpr(mfpr(PR_CCTL) | CCTL_SW_ETM, PR_CCTL); /* * Invalidate caches. */ mtpr(mfpr(PR_CCTL) | 6, PR_CCTL); /* Set cache size and speed */ mtpr(mfpr(PR_BCETSTS), PR_BCETSTS); /* Clear error bits */ mtpr(mfpr(PR_BCEDSTS), PR_BCEDSTS); /* Clear error bits */ mtpr(mfpr(PR_NESTS), PR_NESTS); /* Clear error bits */ start = 0x01400000; s**t = 0x01420000; /* Flush cache lines */ for (; start < s**t; start += 0x20) mtpr(0, start); mtpr((mfpr(PR_CCTL) & ~(CCTL_SW_ETM|CCTL_ENABLE)) | CCTL_HW_ETM, PR_CCTL); start = 0x01000000; s**t = 0x01020000; /* clear tag and valid */ for (; start < s**t; start += 0x20) mtpr(0, start); mtpr(mfpr(PR_CCTL) | 6 | CCTL_ENABLE, PR_CCTL); /* enab. bcache */ start = 0x01800000; s**t = 0x01802000; /* Clear primary cache */ for (; start < s**t; start += 0x20) mtpr(0, start); /* Flush the pipes (via REI) */ __asm("movpsl -(%sp); movab 1f,-(%sp); rei; 1:;"); /* Enable primary cache */ mtpr(PCCTL_P_EN|PCCTL_I_EN|PCCTL_D_EN, PR_PCCTL); /* Enable the VIC */ start = 0; s**t = 0x800; for (; start < s**t; start += 0x20) { mtpr(start, PR_VMAR); mtpr(0, PR_VTAG); } mtpr(ICSR_ENABLE, PR_ICSR); }
void crlintr(void *arg) { struct buf *bp; int i; bp = crltab.crl_buf; i = mfpr(PR_STXCS); switch ((i>>24) & 0xFF) { case CRL_S_XCMPLT: switch (crltab.crl_active) { case CRL_F_RETSTS: { char sbuf[256], sbuf2[256]; crlstat.crl_ds = mfpr(PR_STXDB); snprintb(sbuf, sizeof(sbuf), CRLCS_BITS, crlstat.crl_cs); snprintb(sbuf2, sizeof(sbuf2), CRLDS_BITS, crlstat.crl_ds); printf("crlcs=0x%s, crlds=0x%s\n", sbuf, sbuf2); break; } case CRL_F_READ: case CRL_F_WRITE: bp->b_oflags |= BO_DONE; } crltab.crl_active = 0; wakeup(bp); break; case CRL_S_XCONT: switch (crltab.crl_active) { case CRL_F_WRITE: mtpr(*crltab.crl_xaddr++, PR_STXDB); mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS); break; case CRL_F_READ: *crltab.crl_xaddr++ = mfpr(PR_STXDB); mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS); } break; case CRL_S_ABORT: crltab.crl_active = CRL_F_RETSTS; mtpr(STXCS_IE | CRL_F_RETSTS, PR_STXCS); bp->b_oflags |= BO_DONE; bp->b_error = EIO; break; case CRL_S_RETSTS: crlstat.crl_cs = mfpr(PR_STXDB); mtpr(STXCS_IE | CRL_S_RETSTS, PR_STXCS); break; case CRL_S_HNDSHK: printf("crl: hndshk error\n"); /* dump out some status too? */ crltab.crl_active = 0; bp->b_oflags |= BO_DONE; bp->b_error = EIO; cv_broadcast(&bp->b_done); break; case CRL_S_HWERR: printf("crl: hard error sn%" PRId64 "\n", bp->b_blkno); crltab.crl_active = CRL_F_ABORT; mtpr(STXCS_IE | CRL_F_ABORT, PR_STXCS); break; } }
void ka680_cache_enable() { int start, pslut, fslut, cslut, havevic; /* * Turn caches off. */ mtpr(0, PR_ICSR); mtpr(0, PR_PCCTL); mtpr(mfpr(PR_CCTL) | CCTL_SW_ETM, PR_CCTL); /* * Invalidate caches. */ mtpr(mfpr(PR_CCTL) | 6, PR_CCTL); /* Set cache size and speed */ mtpr(mfpr(PR_BCETSTS), PR_BCETSTS); /* Clear error bits */ mtpr(mfpr(PR_BCEDSTS), PR_BCEDSTS); /* Clear error bits */ mtpr(mfpr(PR_NESTS), PR_NESTS); /* Clear error bits */ switch((vax_siedata & 0xff00) >> 8) { case VAX_STYP_680: case VAX_STYP_681: /* XXX untested */ fslut = 0x01420000; cslut = 0x01020000; havevic = 1; break; case VAX_STYP_690: fslut = 0x01440000; cslut = 0x01040000; havevic = 1; break; case VAX_STYP_691: /* XXX untested */ fslut = 0x01420000; cslut = 0x01020000; havevic = 1; break; case VAX_STYP_694: /* XXX untested */ fslut = 0x01440000; cslut = 0x01040000; havevic = 1; break; case VAX_STYP_675: default: /* unknown cpu; cross fingers */ fslut = 0x01420000; cslut = 0x01020000; havevic = 0; break; } start = 0x01400000; /* Flush cache lines */ for (; start < fslut; start += 0x20) mtpr(0, start); mtpr((mfpr(PR_CCTL) & ~(CCTL_SW_ETM|CCTL_ENABLE)) | CCTL_HW_ETM, PR_CCTL); start = 0x01000000; /* clear tag and valid */ for (; start < cslut; start += 0x20) mtpr(0, start); mtpr(mfpr(PR_CCTL) | 6 | CCTL_ENABLE, PR_CCTL); /* enab. bcache */ start = 0x01800000; pslut = 0x01802000; /* Clear primary cache */ for (; start < pslut; start += 0x20) mtpr(0, start); /* Flush the pipes (via REI) */ asm("movpsl -(sp); movab 1f,-(sp); rei; 1:;"); /* Enable primary cache */ mtpr(PCCTL_P_EN|PCCTL_I_EN|PCCTL_D_EN, PR_PCCTL); /* Enable the VIC */ if (havevic) { int s**t; start = 0; s**t = 0x800; for (; start < s**t; start += 0x20) { mtpr(start, PR_VMAR); mtpr(0, PR_VTAG); } mtpr(ICSR_ENABLE, PR_ICSR); } }
/* enable CRD reports */ ka860_memenable() { mtpr(MERG, mfpr(MERG) & ~M8600_ICRD); }
/* * Try to figure out which type of system this is. */ void findcpu(void) { vax_cpudata = mfpr(PR_SID); vax_cputype = vax_cpudata >> 24; vax_boardtype = vax_cputype << 24; switch (vax_cputype) { case VAX_TYP_730: vax_bustype = VAX_UNIBUS; break; case VAX_TYP_780: vax_bustype = VAX_SBIBUS; break; case VAX_TYP_750: vax_bustype = VAX_CMIBUS; break; case VAX_TYP_790: vax_bustype = VAX_ABUS; break; case VAX_TYP_UV1: vax_bustype = VAX_IBUS; break; case VAX_TYP_UV2: case VAX_TYP_CVAX: case VAX_TYP_RIGEL: case VAX_TYP_MARIAH: case VAX_TYP_NVAX: case VAX_TYP_SOC: vax_siedata = *(int *)(0x20040004); /* SIE address */ vax_boardtype |= vax_siedata >> 24; switch (vax_boardtype) { case VAX_BTYP_420: /* They are very similar */ case VAX_BTYP_410: case VAX_BTYP_43: case VAX_BTYP_46: case VAX_BTYP_48: case VAX_BTYP_IS1: vax_confdata = *(int *)(0x20020000); vax_bustype = VAX_VSBUS; break; case VAX_BTYP_49: vax_confdata = *(int *)(0x25800000); vax_bustype = VAX_VSBUS; break; case VAX_BTYP_9CC: case VAX_BTYP_9RR: case VAX_BTYP_1202: case VAX_BTYP_1302: vax_bustype = VAX_XMIBUS; break; case VAX_BTYP_670: case VAX_BTYP_660: case VAX_BTYP_60: case VAX_BTYP_680: case VAX_BTYP_681: case VAX_BTYP_630: case VAX_BTYP_650: case VAX_BTYP_53: vax_bustype = VAX_IBUS; break; } break; case VAX_TYP_8SS: vax_boardtype = VAX_BTYP_8000; vax_bustype = VAX_BIBUS; break; case VAX_TYP_8NN: vax_boardtype = VAX_BTYP_8800; /* subversion later */ vax_bustype = VAX_NMIBUS; break; case VAX_TYP_8PS: vax_boardtype = VAX_BTYP_8PS; vax_bustype = VAX_NMIBUS; break; default: /* CPU not supported, just give up */ __asm("halt"); } }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ static void niattach(device_t parent, device_t self, void *aux) { struct bi_attach_args *ba = aux; struct ni_softc *sc = device_private(self); struct ifnet *ifp = (struct ifnet *)&sc->sc_if; struct ni_msg *msg; struct ni_ptdb *ptdb; void *va; int i, j, s, res; u_short type; sc->sc_dev = self; type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE); printf(": DEBN%c\n", type == BIDT_DEBNA ? 'A' : type == BIDT_DEBNT ? 'T' : 'K'); sc->sc_iot = ba->ba_iot; sc->sc_ioh = ba->ba_ioh; sc->sc_dmat = ba->ba_dmat; bi_intr_establish(ba->ba_icookie, ba->ba_ivec, niintr, sc, &sc->sc_intrcnt); evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); ni_getpgs(sc, sizeof(struct ni_gvppqb), (void **)&sc->sc_gvppqb, (paddr_t *)&sc->sc_pgvppqb); ni_getpgs(sc, sizeof(struct ni_fqb), (void **)&sc->sc_fqb, 0); ni_getpgs(sc, NBDESCS * sizeof(struct ni_bbd), (void **)&sc->sc_bbd, 0); /* * Zero the newly allocated memory. */ nipqb->np_veclvl = (ba->ba_ivec << 2) + 2; nipqb->np_node = ba->ba_intcpu; nipqb->np_vpqb = (u_int32_t)gvp; #ifdef __vax__ nipqb->np_spt = nipqb->np_gpt = mfpr(PR_SBR); nipqb->np_sptlen = nipqb->np_gptlen = mfpr(PR_SLR); #else #error Must fix support for non-vax. #endif nipqb->np_bvplvl = 1; nipqb->np_vfqb = (u_int32_t)fqb; nipqb->np_vbdt = (u_int32_t)bbd; nipqb->np_nbdr = NBDESCS; /* Free queue block */ nipqb->np_freeq = NQUEUES; fqb->nf_mlen = PKTHDR+MSGADD; fqb->nf_dlen = PKTHDR+TXADD; fqb->nf_rlen = PKTHDR+RXADD; strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = nistart; ifp->if_ioctl = niioctl; ifp->if_watchdog = nitimeout; IFQ_SET_READY(&ifp->if_snd); /* * Start init sequence. */ /* Reset the node */ NI_WREG(BIREG_VAXBICSR, NI_RREG(BIREG_VAXBICSR) | BICSR_NRST); DELAY(500000); i = 20; while ((NI_RREG(BIREG_VAXBICSR) & BICSR_BROKE) && --i) DELAY(500000); if (i == 0) { printf("%s: BROKE bit set after reset\n", device_xname(self)); return; } /* Check state */ if (failtest(sc, NI_PSR, PSR_STATE, PSR_UNDEF, "not undefined state")) return; /* Clear owner bits */ NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN); /* kick off init */ NI_WREG(NI_PCR, (u_int32_t)sc->sc_pgvppqb | PCR_INIT | PCR_OWN); while (NI_RREG(NI_PCR) & PCR_OWN) DELAY(100000); /* Check state */ if (failtest(sc, NI_PSR, PSR_INITED, PSR_INITED, "failed initialize")) return; NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_OWN|PCR_ENABLE); WAITREG(NI_PCR, PCR_OWN); WAITREG(NI_PSR, PSR_OWN); /* Check state */ if (failtest(sc, NI_PSR, PSR_STATE, PSR_ENABLED, "failed enable")) return; NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN); /* * The message queue packets must be located on the beginning * of a page. A VAX page is 512 bytes, but it clusters 8 pages. * This knowledge is used here when allocating pages. * !!! How should this be done on MIPS and Alpha??? !!! */ #if NBPG < 4096 #error pagesize too small #endif s = splvm(); /* Set up message free queue */ ni_getpgs(sc, NMSGBUF * 512, &va, 0); for (i = 0; i < NMSGBUF; i++) { msg = (void *)((char *)va + i * 512); res = INSQTI(msg, &fqb->nf_mforw); } WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); /* Set up xmit queue */ ni_getpgs(sc, NTXBUF * 512, &va, 0); for (i = 0; i < NTXBUF; i++) { struct ni_dg *data; data = (void *)((char *)va + i * 512); data->nd_status = 0; data->nd_len = TXADD; data->nd_ptdbidx = 1; data->nd_opcode = BVP_DGRAM; for (j = 0; j < NTXFRAGS; j++) { data->bufs[j]._offset = 0; data->bufs[j]._key = 1; bbd[i * NTXFRAGS + j].nb_key = 1; bbd[i * NTXFRAGS + j].nb_status = 0; data->bufs[j]._index = i * NTXFRAGS + j; } res = INSQTI(data, &fqb->nf_dforw); } WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_FREEQNE|PCR_DFREEQ|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); /* recv buffers */ ni_getpgs(sc, NRXBUF * 512, &va, 0); for (i = 0; i < NRXBUF; i++) { struct ni_dg *data; int idx; data = (void *)((char *)va + i * 512); data->nd_len = RXADD; data->nd_opcode = BVP_DGRAMRX; data->nd_ptdbidx = 2; data->bufs[0]._key = 1; idx = NTXBUF * NTXFRAGS + i; if (ni_add_rxbuf(sc, data, idx)) panic("niattach: ni_add_rxbuf: out of mbufs"); res = INSQTI(data, &fqb->nf_rforw); } WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); splx(s); /* Set initial parameters */ msg = REMQHI(&fqb->nf_mforw); msg->nm_opcode = BVP_MSG; msg->nm_status = 0; msg->nm_len = sizeof(struct ni_param) + 6; msg->nm_opcode2 = NI_WPARAM; ((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD; endwait = retry = 0; res = INSQTI(msg, &gvp->nc_forw0); retry: WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); i = 1000; while (endwait == 0 && --i) DELAY(10000); if (endwait == 0) { if (++retry < 3) goto retry; printf("%s: no response to set params\n", device_xname(self)); return; } /* Clear counters */ msg = REMQHI(&fqb->nf_mforw); msg->nm_opcode = BVP_MSG; msg->nm_status = 0; msg->nm_len = sizeof(struct ni_param) + 6; msg->nm_opcode2 = NI_RCCNTR; res = INSQTI(msg, &gvp->nc_forw0); WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); /* Enable transmit logic */ msg = REMQHI(&fqb->nf_mforw); msg->nm_opcode = BVP_MSG; msg->nm_status = 0; msg->nm_len = 18; msg->nm_opcode2 = NI_STPTDB; ptdb = (struct ni_ptdb *)&msg->nm_text[0]; memset(ptdb, 0, sizeof(struct ni_ptdb)); ptdb->np_index = 1; ptdb->np_fque = 1; res = INSQTI(msg, &gvp->nc_forw0); WAITREG(NI_PCR, PCR_OWN); NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN); WAITREG(NI_PCR, PCR_OWN); /* Wait for everything to finish */ WAITREG(NI_PSR, PSR_OWN); printf("%s: hardware address %s\n", device_xname(self), ether_sprintf(sc->sc_enaddr)); /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); if (shutdownhook_establish(ni_shutdown, sc) == 0) aprint_error_dev(self, "WARNING: unable to establish shutdown hook\n"); }
void trap(struct trapframe *tf) { u_int sig = 0, type = tf->tf_trap, code = 0; u_int rv, addr; bool trapsig = true; const bool usermode = USERMODE_P(tf); struct lwp * const l = curlwp; struct proc * const p = l->l_proc; struct pcb * const pcb = lwp_getpcb(l); u_quad_t oticks = 0; struct vmspace *vm; struct vm_map *map; vm_prot_t ftype; void *onfault = pcb->pcb_onfault; KASSERT(p != NULL); curcpu()->ci_data.cpu_ntrap++; if (usermode) { type |= T_USER; oticks = p->p_sticks; l->l_md.md_utf = tf; LWP_CACHE_CREDS(l, p); } type &= ~(T_WRITE|T_PTEFETCH); #ifdef TRAPDEBUG if(tf->tf_trap==7) goto fram; if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); fram: #endif switch (type) { default: #ifdef DDB kdb_trap(tf); #endif panic("trap: type %x, code %x, pc %x, psl %x", (u_int)tf->tf_trap, (u_int)tf->tf_code, (u_int)tf->tf_pc, (u_int)tf->tf_psl); case T_KSPNOTVAL: panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, (u_int)tf->tf_fp, (u_int)tf->tf_psl); case T_TRANSFLT|T_USER: case T_TRANSFLT: /* * BUG! BUG! BUG! BUG! BUG! * Due to a hardware bug (at in least KA65x CPUs) a double * page table fetch trap will cause a translation fault * even if access in the SPT PTE entry specifies 'no access'. * In for example section 6.4.2 in VAX Architecture * Reference Manual it states that if a page both are invalid * and have no access set, a 'access violation fault' occurs. * Therefore, we must fall through here... */ #ifdef nohwbug panic("translation fault"); #endif case T_PTELEN|T_USER: /* Page table length exceeded */ case T_ACCFLT|T_USER: if (tf->tf_code < 0) { /* Check for kernel space */ sig = SIGSEGV; code = SEGV_ACCERR; break; } case T_PTELEN: #ifndef MULTIPROCESSOR /* * If we referred to an address beyond the end of the system * page table, it may be due to a failed CAS * restartable-atomic-sequence. If it is, restart it at the * beginning and restart. */ { extern const uint8_t cas32_ras_start[], cas32_ras_end[]; if (tf->tf_code == CASMAGIC && tf->tf_pc >= (uintptr_t) cas32_ras_start && tf->tf_pc < (uintptr_t) cas32_ras_end) { tf->tf_pc = (uintptr_t) cas32_ras_start; trapsig = false; break; } } /* FALLTHROUGH */ #endif case T_ACCFLT: #ifdef TRAPDEBUG if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); #endif #ifdef DIAGNOSTIC if (p == 0) panic("trap: access fault: addr %lx code %lx", tf->tf_pc, tf->tf_code); if (tf->tf_psl & PSL_IS) panic("trap: pflt on IS"); #endif /* * Page tables are allocated in pmap_enter(). We get * info from below if it is a page table fault, but * UVM may want to map in pages without faults, so * because we must check for PTE pages anyway we don't * bother doing it here. */ addr = trunc_page(tf->tf_code); if (!usermode && (tf->tf_code < 0)) { vm = NULL; map = kernel_map; } else { vm = p->p_vmspace; map = &vm->vm_map; } if (tf->tf_trap & T_WRITE) ftype = VM_PROT_WRITE; else ftype = VM_PROT_READ; pcb->pcb_onfault = NULL; rv = uvm_fault(map, addr, ftype); pcb->pcb_onfault = onfault; if (rv != 0) { if (!usermode) { if (onfault) { pcb->pcb_onfault = NULL; tf->tf_pc = (unsigned)onfault; tf->tf_psl &= ~PSL_FPD; tf->tf_r0 = rv; return; } printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ", tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3); printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7); printf( "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11); printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n", tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc); panic("SEGV in kernel mode: pc %#lx addr %#lx", tf->tf_pc, tf->tf_code); } switch (rv) { case ENOMEM: printf("UVM: pid %d (%s), uid %d killed: " "out of swap\n", p->p_pid, p->p_comm, l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); sig = SIGKILL; code = SI_NOINFO; break; case EINVAL: code = BUS_ADRERR; sig = SIGBUS; break; case EACCES: code = SEGV_ACCERR; sig = SIGSEGV; break; default: code = SEGV_MAPERR; sig = SIGSEGV; break; } } else { trapsig = false; if (map != kernel_map && addr > 0 && (void *)addr >= vm->vm_maxsaddr) uvm_grow(p, addr); } break; case T_BPTFLT|T_USER: sig = SIGTRAP; code = TRAP_BRKPT; break; case T_TRCTRAP|T_USER: sig = SIGTRAP; code = TRAP_TRACE; tf->tf_psl &= ~PSL_T; break; case T_PRIVINFLT|T_USER: sig = SIGILL; code = ILL_PRVOPC; break; case T_RESADFLT|T_USER: sig = SIGILL; code = ILL_ILLADR; break; case T_RESOPFLT|T_USER: sig = SIGILL; code = ILL_ILLOPC; break; case T_XFCFLT|T_USER: sig = SIGEMT; break; case T_ARITHFLT|T_USER: sig = SIGFPE; switch (tf->tf_code) { case ATRP_INTOVF: code = FPE_INTOVF; break; case ATRP_INTDIV: code = FPE_INTDIV; break; case ATRP_FLTOVF: code = FPE_FLTOVF; break; case ATRP_FLTDIV: code = FPE_FLTDIV; break; case ATRP_FLTUND: code = FPE_FLTUND; break; case ATRP_DECOVF: code = FPE_INTOVF; break; case ATRP_FLTSUB: code = FPE_FLTSUB; break; case AFLT_FLTDIV: code = FPE_FLTDIV; break; case AFLT_FLTUND: code = FPE_FLTUND; break; case AFLT_FLTOVF: code = FPE_FLTOVF; break; default: code = FPE_FLTINV; break; } break; case T_ASTFLT|T_USER: mtpr(AST_NO,PR_ASTLVL); trapsig = false; if (curcpu()->ci_want_resched) preempt(); break; #ifdef DDB case T_BPTFLT: /* Kernel breakpoint */ case T_KDBTRAP: case T_KDBTRAP|T_USER: case T_TRCTRAP: kdb_trap(tf); return; #endif } if (trapsig) { ksiginfo_t ksi; if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps && (p->p_slflag & PSL_TRACED) == 0 && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); KSI_INIT_TRAP(&ksi); ksi.ksi_signo = sig; ksi.ksi_trap = tf->tf_trap; ksi.ksi_addr = (void *)tf->tf_code; ksi.ksi_code = code; /* * Arithmetic exceptions can be of two kinds: * - traps (codes 1..7), where pc points to the * next instruction to execute. * - faults (codes 8..10), where pc points to the * faulting instruction. * In the latter case, we need to advance pc by ourselves * to prevent a signal loop. * * XXX this is gross -- miod */ if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) tf->tf_pc = skip_opcode(tf->tf_pc); trapsignal(l, &ksi); } if (!usermode) return; userret(l, tf, oticks); }