void ka660_cache_enable() { unsigned int *p; int cnt, bnk, behrtmp; mtpr(0, KA660_CCR); /* Disable cache */ mtpr(CCR_DIA, KA660_CCR); /* Switch to diag mode */ bnk = 1; behrtmp = 0; while(bnk <= 0x80) { *(int *)KA660_BEHR = bnk; p = (int *)KA660_CDATA; *p = 0x55aaff00L; if(*p == 0x55aaff00L) behrtmp |= bnk; *p = 0xffaa0055L; if(*p != 0xffaa0055L) behrtmp &= ~bnk; cnt = 256; while(cnt--) *p++ = 0L; p = (int *) KA660_CTAG; cnt =128; while(cnt--) { *p++ = 0x80000000L; p++; } bnk <<= 1; } *(int *)KA660_BEHR = behrtmp; mtpr(CCR_DIA|CCR_FLU, KA660_CCR); /* Flush tags */ mtpr(CCR_ENA, KA660_CCR); /* Enable cache */ }
void ka46_cache_enable() { int i, *tmp; /* Disable caches */ *(int *)KA46_CCR &= ~CCR_SPECIO;/* secondary */ mtpr(PCSTS_FLUSH, PR_PCSTS); /* primary */ *(int *)KA46_BWF0 &= ~BWF0_FEN; /* invalidate filter */ /* Clear caches */ tmp = (void *)KA46_INVFLT; /* inv filter */ for (i = 0; i < 32768; i++) tmp[i] = 0; /* Write valid parity to all primary cache entries */ for (i = 0; i < 256; i++) { mtpr(i << 3, PR_PCIDX); mtpr(PCTAG_PARITY, PR_PCTAG); } /* Secondary cache */ tmp = (void *)KA46_TAGST; for (i = 0; i < KA46_TAGSZ*2; i+=2) tmp[i] = 0; /* Enable cache */ *(int *)KA46_BWF0 |= BWF0_FEN; /* invalidate filter */ mtpr(PCSTS_ENABLE, PR_PCSTS); *(int *)KA46_CCR = CCR_SPECIO | CCR_CENA; }
void cfltint(int arg) { struct buf *bp = cfltab.cfl_buf; switch (cfltab.cfl_active) { case CFL_START:/* do a read */ mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT, PR_TXDB); cfltab.cfl_active = CFL_SECTOR; break; case CFL_SECTOR:/* send sector */ mtpr(FLOP_DATA | (int)bp->b_blkno % (CFL_SECTORS + 1), PR_TXDB); cfltab.cfl_active = CFL_TRACK; break; case CFL_TRACK: mtpr(FLOP_DATA | (int)bp->b_blkno / CFL_SECTORS, PR_TXDB); cfltab.cfl_active = CFL_NEXT; break; case CFL_NEXT: mtpr(FLOP_DATA | *cfltab.cfl_xaddr++, PR_TXDB); if (--bp->b_bcount == 0) cfltab.cfl_active = CFL_FINISH; break; } }
/* One must explicitly check that the TB is valid and the FOE bit is reset */ static void update_itb (void) { /* This writes into a temp register, not the actual one */ mtpr(TB_TAG); mtpr(TB_CTL); /* This commits the TB update */ mtpr(ITB_PTE); }
void configure() { extern int boothowto; if (config_rootfound("backplane", NULL) == NULL) panic("backplane not configured"); #if GENERIC if ((boothowto & RB_ASKNAME) == 0) setroot(); setconf(); #else setroot(); #endif /* * Configure swap area and related system * parameter based on device(s) used. */ swapconf(); dumpconf(); cold = 0; mtpr(GC_CCF, PR_TXDB); /* Clear cold start flag in cpu */ }
/* * Init the SCB and set up a handler for all vectors in the lower space, * to detect unwanted interrupts. */ void scb_init(void) { unsigned i; /* * Allocate space. We need one page for the SCB, and 128*20 == 2.5k * for the vectors. The SCB must be on a page boundary. */ i = (unsigned)alloc(VAX_NBPG + 128*sizeof(scb_vec[0])) + VAX_PGOFSET; i &= ~VAX_PGOFSET; mtpr(i, PR_SCBB); scb = (void *)i; scb_vec = (struct ivec_dsp *)(i + VAX_NBPG); for (i = 0; i < 128; i++) { scb[i] = &scb_vec[i]; scb[i] = (void *)((unsigned)scb[i] | SCB_ISTACK); /* Only interrupt stack */ scb_vec[i] = idsptch; scb_vec[i].hoppaddr = scb_stray; scb_vec[i].pushlarg = (void *) (i * 4); scb_vec[i].ev = 0; } /* soft interrupt under IPL 3 used to handle context switches. we need to go in/out with maximum control so we handle this interrupt aside */ scb[0x8c/4] = (void *)((unsigned long)switchto); scb[0x8c/4] = (void *)((unsigned)scb[0x8c/4] | SCB_ISTACK); /* Only interrupt stack */ }
void ka48_conf() { char *cpuname; switch((vax_siedata >> 8) & 0xFF) { case VAX_STYP_45: cpuname = "KA45"; break; case VAX_STYP_48: cpuname = "KA48"; break; default: cpuname = "Unknown SOC"; } printf("cpu: %s\n", cpuname); ka48_cpu = (void *)vax_map_physmem(VS_REGS, 1); printf("cpu: turning on floating point chip\n"); mtpr(2, PR_ACCS); /* Enable floating points */ /* * 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(VS_CLOCK, 1); }
/* * 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); }
int ka53_mchk(void *addr) { mtpr(0x00, PR_MCESR); printf("Machine Check\n"); return 0; }
/* * Determine i/o configuration for a machine. */ configure() { register int *ip; extern caddr_t Sysbase; vbafind(numvba, (caddr_t)vmem, VMEMmap); numvba++; /* * Write protect the scb. It is strange * that this code is here, but this is as soon * as we are done mucking with it, and the * write-enable was done in assembly language * to which we will never return. */ ip = (int *)&Sysmap[2]; *ip &= ~PG_PROT; *ip |= PG_KR; mtpr(TBIS, Sysbase+2*NBPG); #if GENERIC if ((boothowto & RB_ASKNAME) == 0) setroot(); setconf(); #else setroot(); #endif /* * Configure swap area and related system * parameter based on device(s) used. */ swapconf(); cold = 0; }
void ka730_clrf(void) { int s = splhigh(); #define WAIT while ((mfpr(PR_TXCS) & GC_RDY) == 0) ; WAIT; mtpr(GC_CWFL|GC_CONS, PR_TXDB); WAIT; mtpr(GC_CCFL|GC_CONS, PR_TXDB); WAIT; splx(s); }
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 ka48_cache_enable() { int i, *tmp; long *par_ctl = (long *)KA48_PARCTL; /* Disable cache */ mtpr(0, PR_CADR); /* disable */ *par_ctl &= ~KA48_PARCTL_INVENA; /* clear ? invalid enable */ mtpr(2, PR_CADR); /* flush */ /* Clear caches */ tmp = (void *)KA48_INVFLT; /* inv filter */ for (i = 0; i < KA48_INVFLTSZ / sizeof(int); i++) tmp[i] = 0; *par_ctl |= KA48_PARCTL_INVENA; /* Enable ???? */ mtpr(4, PR_CADR); /* enable cache */ *par_ctl |= (KA48_PARCTL_AGS | /* AGS? */ KA48_PARCTL_NPEN | /* N? Parity Enable */ KA48_PARCTL_CPEN); /* Cpu parity enable */ }
/* 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 ka46_conf() { printf("cpu: KA46\n"); ka46_cpu = (void *)vax_map_physmem(VS_REGS, 1); printf("cpu: turning on floating point chip\n"); mtpr(2, PR_ACCS); /* Enable floating points */ /* * 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(VS_CLOCK, 1); }
/* * Returns last vector/ipl referenced. Clears vector/ipl after reading. */ int scb_vecref(int *rvec, int *ripl) { int save; if (rvec) *rvec = vector; if (ripl) *ripl = ipl; save = gotintr; gotintr = vector = ipl = 0; mtpr(0, PR_IPL); return save; }
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 timer_handler(void *arg) { tickcnt++; mtpr(0xc1, PR_ICCS); /* start multitask? */ if ((sched_on == 1) && (sched_running == 0)) { sched_running = 1; } /* stop multitask? */ if (current_process == 0) { if ((sched_on == 0) && (sched_running == 1)) { sched_running = 0; } } /* schedule? */ if (sched_running) { switch_context(); /* schedule and pre-dispatch in clock IPL */ mtpr(3, PR_SIRR); /* request soft int in IPL 3 to real hardware switch */ } }
void cpu_startup(void) { #if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY vaddr_t minaddr, maxaddr; #endif char pbuf[9]; /* * Initialize error message buffer. */ initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); /* * Good {morning,afternoon,evening,night}. * Also call CPU init on systems that need that. */ printf("%s%s", copyright, version); printf("%s\n", cpu_getmodel()); if (dep_call->cpu_conf) (*dep_call->cpu_conf)(); format_bytes(pbuf, sizeof(pbuf), avail_end); printf("total memory = %s\n", pbuf); panicstr = NULL; mtpr(AST_NO, PR_ASTLVL); spl0(); #if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY minaddr = 0; /* * Allocate a submap for physio. This map effectively limits the * number of processes doing physio at any one time. */ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 0, false, NULL); #endif format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); printf("avail memory = %s\n", pbuf); #ifdef DDB if (boothowto & RB_KDB) Debugger(); #endif iomap_ex_malloc_safe = 1; }
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 }
/* * 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); }
static void nmi_mainbus_attach(struct device *parent, struct device *self, void *aux) { struct nmi_attach_args na; int nbia, *r = 0; printf("\n"); /* One CPU is always found */ na.slot = 20; config_found(self, (void *)&na, nmi_mainbus_print); /* Check for a second one */ if (vax_boardtype == VAX_BTYP_8800) { na.slot = 21; config_found(self, (void *)&na, nmi_mainbus_print); } /* One memory adapter is also present */ na.slot = 10; config_found(self, (void *)&na, nmi_mainbus_print); /* Enable BI interrupts */ mtpr(NICTRL_DEV0|NICTRL_DEV1|NICTRL_MNF, PR_NICTRL); /* Search for NBIA/NBIB adapters */ for (nbia = 0; nbia < 2; nbia++) { if (r) vax_unmap_physmem((vaddr_t)r, 1); r = (int *)vax_map_physmem(NBIA_REGS(nbia), 1); if (badaddr((caddr_t)r, 4)) continue; na.slot = 2 * nbia; if (r[1] & 2) config_found(self, (void *)&na, nmi_mainbus_print); na.slot++; if (r[1] & 4) config_found(self, (void *)&na, nmi_mainbus_print); } }
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 }
ka820_init() { register int csr; /* map in the various devices */ *(int *)&Ka820map[0] = PG_V|PG_KW|btop(KA820_PORTADDR); *(int *)&RX50map[0] = PG_V|PG_KW|btop(KA820_RX50ADDR); *(int *)&Clockmap[0] = PG_V|PG_KW|btop(KA820_CLOCKADDR); #ifdef notyet ioaccess(bootram, BRAMmap, KA820_BRPAGES * NBPG); ioaccess(eeprom, EEPROMmap, KA820_EEPAGES * NBPG); #else mtpr(TBIA, 0); #endif /* reset the console and enable the RX50 */ csr = ka820port.csr; csr &= ~KA820PORT_RSTHALT; /* ??? */ csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN | KA820PORT_RXIE; ka820port.csr = csr; }
void ka410_conf(void) { struct cpu_info * const ci = curcpu(); struct vs_cpu *ka410_cpu; ka410_cpu = (struct vs_cpu *)vax_map_physmem(VS_REGS, 1); switch (vax_cputype) { case VAX_TYP_UV2: ka410_cpu->vc_410mser = 1; ci->ci_cpustr = "KA410, UV2"; break; case VAX_TYP_CVAX: ka410_cpu->vc_vdcorg = 0; /* XXX */ ka410_cpu->vc_parctl = PARCTL_CPEN | PARCTL_DPEN ; mtpr(KA420_CADR_S2E|KA420_CADR_S1E|KA420_CADR_ISE|KA420_CADR_DSE, PR_CADR); if (vax_confdata & KA420_CFG_CACHPR) { l2cache = (void *)vax_map_physmem(KA420_CH2_BASE, (KA420_CH2_SIZE / VAX_NBPG)); cacr = (void *)vax_map_physmem(KA420_CACR, 1); ka41_cache_enable(); ci->ci_cpustr = "KA420, CVAX, 1KB L1 cache, 64KB L2 cache"; } else { ci->ci_cpustr = "KA420, CVAX, 1KB L1 cache"; } } /* Done with ka410_cpu - release it */ vax_unmap_physmem((vaddr_t)ka410_cpu, 1); /* * 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(KA420_WAT_BASE, 1); }
/* * Generates a new SCB. */ paddr_t scb_init(paddr_t avail_start) { struct ivec_dsp **ivec = (struct ivec_dsp **)avail_start; struct ivec_dsp **old = (struct ivec_dsp **)KERNBASE; vaddr_t vavail = avail_start + KERNBASE; int scb_size = dep_call->cpu_scbsz; int i; scb = (struct scb *)vavail; scb_vec = (struct ivec_dsp *)(vavail + (scb_size * VAX_NBPG)); /* Init the whole SCB with interrupt catchers */ for (i = 0; i < (scb_size * VAX_NBPG)/4; i++) { ivec[i] = &scb_vec[i]; (int)ivec[i] |= SCB_ISTACK; /* On istack, please */ scb_vec[i] = idsptch; scb_vec[i].hoppaddr = scb_stray; scb_vec[i].pushlarg = (void *) (i * 4); scb_vec[i].ev = NULL; } /* * Copy all pre-set interrupt vectors to the new SCB. * It is known that these vectors is at KERNBASE from the * beginning, and that if the vector is zero it should call * stray instead. */ for (i = 0; i < 64; i++) if (old[i]) ivec[i] = old[i]; /* Last action: set the SCB */ mtpr(avail_start, PR_SCBB); /* Return new avail_start. Also save space for the dispatchers. */ return avail_start + (1 + sizeof(struct ivec_dsp) / sizeof(void *)) * scb_size * VAX_NBPG; };
void ka410_conf() { struct vs_cpu *ka410_cpu; ka410_cpu = (struct vs_cpu *)vax_map_physmem(VS_REGS, 1); switch (vax_cputype) { case VAX_TYP_UV2: ka410_cpu->vc_410mser = 1; printf("cpu: KA410\n"); break; case VAX_TYP_CVAX: printf("cpu: KA41/42\n"); ka410_cpu->vc_vdcorg = 0; /* XXX */ ka410_cpu->vc_parctl = PARCTL_CPEN | PARCTL_DPEN ; printf("cpu: Enabling primary cache, "); mtpr(KA420_CADR_S2E|KA420_CADR_S1E|KA420_CADR_ISE|KA420_CADR_DSE, PR_CADR); if (vax_confdata & KA420_CFG_CACHPR) { l2cache = (void *)vax_map_physmem(KA420_CH2_BASE, (KA420_CH2_SIZE / VAX_NBPG)); cacr = (void *)vax_map_physmem(KA420_CACR, 1); printf("secondary cache\n"); ka41_cache_enable(); } else printf("no secondary cache present\n"); } /* Done with ka410_cpu - release it */ vax_unmap_physmem((vaddr_t)ka410_cpu, 1); /* * 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(KA420_WAT_BASE, 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 */ }
void ka46_conf() { switch(vax_siedata & 0xFF) { case VAX_VTYP_47: printf("cpu: KA47\n"); break; case VAX_VTYP_46: printf("cpu: KA46\n"); break; default: printf("cpu: Unknown Mariah\n"); } ka46_cpu = (void *)vax_map_physmem(VS_REGS, 1); printf("cpu: turning on floating point chip\n"); mtpr(2, PR_ACCS); /* Enable floating points */ /* * 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(VS_CLOCK, 1); }