void viking_cache_enable(void) { u_int pcr; pcr = lda(SRMMU_PCR, ASI_SRMMU); if ((pcr & VIKING_PCR_ICE) == 0) { /* I-cache not on; "flash-clear" it now. */ sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */ sta(0, ASI_ICACHECLR, 0); /* clear */ } if ((pcr & VIKING_PCR_DCE) == 0) { /* D-cache not on: "flash-clear" it. */ sta(0x80000000, ASI_DCACHECLR, 0); sta(0, ASI_DCACHECLR, 0); } /* Turn on caches via MMU */ sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE); CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1; /* Now turn on MultiCache if it exists */ if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) { /* Set external cache enable bit in MXCC control register */ stda(MXCC_CTRLREG, ASI_CONTROL, ldda(MXCC_CTRLREG, ASI_CONTROL) | MXCC_CTRLREG_CE); cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */ CACHEINFO.ec_enabled = 1; } }
/* * Switch video mode and clear screen */ void tcx_s24_reset(struct tcx_softc *sc, int depth) { struct rasops_info *ri = &sc->sc_sunfb.sf_ro; uint32_t pixel; paddr_t dst; int n; if (depth == 8) pixel = TCX_CTL_8_MAPPED | (ri->ri_devcmap[WSCOL_WHITE] & 0xff); else pixel = TCX_CTL_24_LEVEL | 0xffffff; /* * Set the first 32 pixels as white in the intended mode, using the * control plane. */ dst = sc->sc_cplane; for (n = 32; n != 0; n--) { sta(dst, ASI_BYPASS, pixel); dst += 4; } /* * Do the remaining pixels: either with the blitter if we can use it, * or continuing manual writes if we can't. */ if (sc->sc_blit != 0) { dst = sc->sc_blit + (32 << 3); pixel = ((sc->sc_blit_width - 1) << 24) | 0; for (n = sc->sc_sunfb.sf_fbsize - 32; n != 0; n -= sc->sc_blit_width) { stda(dst, ASI_BYPASS, pixel); dst += sc->sc_blit_width << 3; } } else { /* this relies on video memory being contiguous */ for (n = sc->sc_sunfb.sf_fbsize - 32; n != 0; n--) { sta(dst, ASI_BYPASS, pixel); dst += 4; } } }
/* * Perform a stipple operation rop from (x, y) to (x + cnt - 1, y). * * We probably should honour the stipple alignment property (stipple-align), * in case it is different than 32 (1 << 5). However, due to the way * the stipple space is accessed, it is not possible to have a stricter * alignment requirement, so let's settle for 32. There probably haven't * been TCX boards with relaxed alignment rules anyway. */ void tcx_stipple(struct tcx_softc *sc, int x, int y, int cnt, int rop, int bg) { int rx; /* aligned x */ int lbcnt; /* count of untouched pixels on the left */ int rbcnt; /* count of untouched pixels on the right */ uint32_t wmask; /* write mask */ uint32_t soffs; /* stipple offset */ uint64_t scmd; scmd = rop << STIPPLE_ROP_SHIFT; scmd |= TCX_CTL_8_MAPPED | bg; /* pixel bits, here in 8-bit mode */ scmd <<= 32; /* * The first pass needs to align the position to a 32 pixel * boundary, which explains why the loop is a bit unnatural * at first glance. */ rx = x & ~(32 - 1); soffs = sc->sc_stipple + ((y * sc->sc_sunfb.sf_width + rx) << 3); lbcnt = x - rx; wmask = 0xffffffff >> lbcnt; while (cnt != 0) { rbcnt = (32 - lbcnt) - cnt; if (rbcnt < 0) rbcnt = 0; if (rbcnt != 0) wmask &= ~((1 << rbcnt) - 1); stda(soffs, ASI_BYPASS, scmd | wmask); cnt -= (32 - lbcnt) - rbcnt; soffs += 32 << 3; /* further loops are aligned */ lbcnt = 0; wmask = 0xffffffff; } }
/* * Perform a blit operation, copying the line starting at computed * position src to computed position dst, for a length of len pixels. */ void tcx_blit(struct tcx_softc *sc, uint32_t dst, uint32_t src, int len) { int cx; uint32_t addr; addr = sc->sc_blit + (dst << 3); /* do the incomplete chunk first if needed */ cx = len & (sc->sc_blit_width - 1); if (cx == 0) cx = sc->sc_blit_width; while (len != 0) { stda(addr, ASI_BYPASS, ((cx - 1) << 24) | src); src += cx; addr += cx << 3; len -= cx; /* and then full steam ahead for the others */ cx = sc->sc_blit_width; } }
void viking_cache_enable() { u_int pcr; cache_alias_dist = max( CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity, CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity); cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET; pcr = lda(SRMMU_PCR, ASI_SRMMU); if ((pcr & VIKING_PCR_ICE) == 0) { /* I-cache not on; "flash-clear" it now. */ sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */ sta(0, ASI_ICACHECLR, 0); /* clear */ } if ((pcr & VIKING_PCR_DCE) == 0) { /* D-cache not on: "flash-clear" it. */ sta(0x80000000, ASI_DCACHECLR, 0); sta(0, ASI_DCACHECLR, 0); } /* Turn on caches via MMU */ sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE); CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1; /* Now turn on MultiCache if it exists */ if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) { /* Multicache controller */ stda(MXCC_ENABLE_ADDR, ASI_CONTROL, ldda(MXCC_ENABLE_ADDR, ASI_CONTROL) | (u_int64_t)MXCC_ENABLE_BIT); cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */ CACHEINFO.ec_enabled = 1; } printf("cache enabled\n"); }
int tcx_putchar(void *cookie, int row, int col, u_int uc, long attr) { struct rasops_info *ri = cookie; struct tcx_softc *sc = ri->ri_hw; struct wsdisplay_font *font = ri->ri_font; int fg, bg, ul; int h, x, y; uint8_t *fontbits; uint32_t fgpattern, bgpattern; ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, &ul); fg = ri->ri_devcmap[fg] & 0xff; /* 8 bit palette index */ bg = ri->ri_devcmap[bg] & 0xff; /* 8 bit palette index */ x = ri->ri_xorigin + col * font->fontwidth; y = ri->ri_yorigin + row * font->fontheight; if (uc == ' ') { /* inline tcx_erasecols(cookie, row, col, 1, attr) */ for (h = font->fontheight; h != 0; y++, h--) tcx_stipple(sc, x, y, font->fontwidth, GXcopy, h == 2 && ul != 0 ? fg : bg); } else { int rx; int lbcnt, rbcnt; uint32_t soffs; uint64_t stmpl, scmd; stmpl = (GXcopy << STIPPLE_ROP_SHIFT) | TCX_CTL_8_MAPPED; fontbits = (uint8_t *)font->data + (uc - font->firstchar) * ri->ri_fontscale; rx = x & ~(32 - 1); lbcnt = x - rx; rbcnt = (32 - lbcnt) - font->fontwidth; /* may be negative */ soffs = sc->sc_stipple + ((y * sc->sc_sunfb.sf_width + rx) << 3); for (h = font->fontheight; h != 0; y++, h--) { if (font->fontwidth <= 8) fgpattern = *(uint8_t *)fontbits >> (8 - font->fontwidth); else /* if (font->fontwidth <= 16) */ fgpattern = *(uint16_t *)fontbits >> (16 - font->fontwidth); /* see tcx_accel_plug() for the reason why larger font sizes are not supported, yet */ fontbits += font->stride; /* underline */ if (ul && h == 2) fgpattern = 0xffffffff & ((1 << font->fontwidth) - 1); bgpattern = ~fgpattern & ((1 << font->fontwidth) - 1); /* * We have a pattern of font->fontwidth bits in * the low bits of `fgpattern' and its one-complement * in `bgpattern'. The bgpattern bits need to be * painted with the background colour, while the * fgpattern bits need to be painted with the * foreground colour. * * The particular character cell position might * span two stipple cells, so we have to account * for this. */ if (rbcnt >= 0) { /* everything fits in one stipple cell. */ /* foreground */ scmd = (stmpl | fg) << 32; stda(soffs, ASI_BYPASS, scmd | (fgpattern << rbcnt)); /* background */ scmd = (stmpl | bg) << 32; stda(soffs, ASI_BYPASS, scmd | (bgpattern << rbcnt)); } else { /* needs two stipple cells. */ /* foreground, first stipple cell */ scmd = (stmpl | fg) << 32; stda(soffs, ASI_BYPASS, scmd | (fgpattern >> -rbcnt)); /* background, first stipple cell */ scmd = (stmpl | bg) << 32; stda(soffs, ASI_BYPASS, scmd | (bgpattern >> -rbcnt)); /* rotate patterns, relying on 32 bit size */ fgpattern <<= (32 + rbcnt); bgpattern <<= (32 + rbcnt); /* foreground, second stipple cell */ scmd = (stmpl | fg) << 32; stda(soffs + (32 << 3), ASI_BYPASS, scmd | fgpattern); /* background, second stipple cell */ scmd = (stmpl | bg) << 32; stda(soffs + (32 << 3), ASI_BYPASS, scmd | bgpattern); } soffs += sc->sc_sunfb.sf_width << 3; } }