Index: src/sys/dev/wscons/wsdisplay_vcons.c diff -u src/sys/dev/wscons/wsdisplay_vcons.c:1.64 src/sys/dev/wscons/wsdisplay_vcons.c:1.65 --- src/sys/dev/wscons/wsdisplay_vcons.c:1.64 Mon Jul 18 11:09:22 2022 +++ src/sys/dev/wscons/wsdisplay_vcons.c Tue Feb 14 08:14:02 2023 @@ -121,7 +121,7 @@ static void vcons_erasecols_buffer(void *, int, int, int, long); static void vcons_copyrows_buffer(void *, int, int, int); static void vcons_eraserows_buffer(void *, int, int, long); -static void vcons_putchar_buffer(void *, int, int, u_int, long); +static int vcons_putchar_buffer(void *, int, int, u_int, long); /* * actual wrapper methods which call both the _buffer ones above and the @@ -1237,22 +1237,25 @@ vcons_unlock(scr); } -static void +static int vcons_putchar_buffer(void *cookie, int row, int col, u_int c, long attr) { struct rasops_info *ri = cookie; struct vcons_screen *scr = ri->ri_hw; int offset = vcons_offset_to_zero(scr); - int pos; + int pos, ret = 0; if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) && (col < ri->ri_cols)) { pos = col + row * ri->ri_cols; + ret = (scr->scr_attrs[pos + offset] != attr) || + (scr->scr_chars[pos + offset] != c); scr->scr_attrs[pos + offset] = attr; scr->scr_chars[pos + offset] = c; } - vcons_dirty(scr); + if (ret) vcons_dirty(scr); + return ret; } #ifdef VCONS_DRAW_INTR @@ -1282,8 +1285,9 @@ { struct rasops_info *ri = cookie; struct vcons_screen *scr = ri->ri_hw; - - vcons_putchar_buffer(cookie, row, col, c, attr); + int need_draw; + + need_draw = vcons_putchar_buffer(cookie, row, col, c, attr); if (vcons_use_intr(scr)) return; @@ -1291,12 +1295,13 @@ vcons_lock(scr); if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { #ifdef VCONS_DRAW_INTR - vcons_putchar_cached(cookie, row, col, c, attr); + if (need_draw) vcons_putchar_cached(cookie, row, col, c, attr); #else if (row == ri->ri_crow && col == ri->ri_ccol) { ri->ri_flg &= ~RI_CURSOR; - } - scr->putchar(cookie, row, col, c, attr); + scr->putchar(cookie, row, col, c, attr); + } else if (need_draw) + scr->putchar(cookie, row, col, c, attr); #endif } vcons_unlock(scr); Index: src/sys/dev/wscons/wsdisplay_vcons.c diff -u src/sys/dev/wscons/wsdisplay_vcons.c:1.65 src/sys/dev/wscons/wsdisplay_vcons.c:1.66 --- src/sys/dev/wscons/wsdisplay_vcons.c:1.65 Tue Feb 14 08:14:02 2023 +++ src/sys/dev/wscons/wsdisplay_vcons.c Tue Feb 14 08:22:02 2023 @@ -478,7 +478,14 @@ flags |= WSFONT_FIND_ALPHA; } - fcookie = wsfont_find(f->name, 0, 0, 0, 0, 0, flags); + fcookie = wsfont_find(f->name, 0, 0, 0, + /* bitorder */ + scr->scr_flags & VCONS_FONT_BITS_R2L ? + WSDISPLAY_FONTORDER_R2L : WSDISPLAY_FONTORDER_L2R, + /* byteorder */ + scr->scr_flags & VCONS_FONT_BYTES_R2L ? + WSDISPLAY_FONTORDER_R2L : WSDISPLAY_FONTORDER_L2R, + flags); if (fcookie == -1) return EINVAL; Index: src/sys/dev/wscons/wsdisplay_vconsvar.h diff -u src/sys/dev/wscons/wsdisplay_vconsvar.h:1.33 src/sys/dev/wscons/wsdisplay_vconsvar.h:1.34 --- src/sys/dev/wscons/wsdisplay_vconsvar.h:1.33 Sun Jul 17 20:23:17 2022 +++ src/sys/dev/wscons/wsdisplay_vconsvar.h Tue Feb 14 08:22:02 2023 @@ -70,6 +70,11 @@ #define VCONS_LOADFONT 0x40 /* driver can load_font() */ #define VCONS_NO_CURSOR 0x80 /* use putchar() based cursor(), to * avoid fb reads */ +#define VCONS_FONT_BITS_R2L 0x100 /* request right-to-left bitorder in + * wsfont_find() */ +#define VCONS_FONT_BYTES_R2L 0x200 /* request right-to-left byteorder in + * wsfont_find() */ + /* status flags used by vcons */ uint32_t scr_status; #define VCONS_IS_VISIBLE 1 /* this screen is currently visible */ Index: src/sys/arch/sparc/dev/sx.c diff -u src/sys/arch/sparc/dev/sx.c:1.5 src/sys/arch/sparc/dev/sx.c:1.6 --- src/sys/arch/sparc/dev/sx.c:1.5 Sat Sep 11 20:28:05 2021 +++ src/sys/arch/sparc/dev/sx.c Thu Apr 13 13:07:48 2023 @@ -104,7 +104,7 @@ sx_write(sc, SX_PAGE_BOUND_LOWER, 0xfc000000); /* cg14 takes up the whole 64MB chunk */ sx_write(sc, SX_PAGE_BOUND_UPPER, 0xffffffff); - sx_write(sc, SX_DIAGNOSTICS, 0); + sx_write(sc, SX_DIAGNOSTICS, SX_DIAG_INIT); sx_write(sc, SX_PLANEMASK, 0xffffffff); /* Index: src/sys/arch/sparc/dev/cgfourteen.c diff -u src/sys/arch/sparc/dev/cgfourteen.c:1.93 src/sys/arch/sparc/dev/cgfourteen.c:1.94 --- src/sys/arch/sparc/dev/cgfourteen.c:1.93 Wed May 25 21:01:04 2022 +++ src/sys/arch/sparc/dev/cgfourteen.c Tue May 23 10:20:12 2023 @@ -168,6 +168,19 @@ static void cg14_erasecols(void *, int, int, int, long); static void cg14_copyrows(void *, int, int, int); static void cg14_eraserows(void *, int, int, long); + +/* + * issue ALU instruction: + * sxi(OPCODE, srcA, srcB, dest, count) + */ +#define sxi(inst, a, b, d, cnt) sx_write(sc->sc_sx, SX_INSTRUCTIONS, inst((a), (b), (d), (cnt))) + +/* + * issue memory referencing instruction: + * sxm(OPCODE, address, start register, count) + */ +#define sxm(inst, addr, reg, count) sta((addr) & ~7, ASI_SX, inst((reg), (count), (addr) & 7)) + #endif /* NSX > 0 */ #endif @@ -358,7 +371,7 @@ sc->sc_fbaddr, 0, 0, 0) & 0xfffff000; aprint_normal_dev(sc->sc_dev, "using %s\n", device_xname(sc->sc_sx->sc_dev)); - aprint_debug_dev(sc->sc_dev, "fb paddr: %08x\n", + aprint_normal_dev(sc->sc_dev, "fb paddr: %08x\n", sc->sc_fb_paddr); sx_write(sc->sc_sx, SX_PAGE_BOUND_LOWER, sc->sc_fb_paddr); sx_write(sc->sc_sx, SX_PAGE_BOUND_UPPER, @@ -379,7 +392,7 @@ * the last close. This kind of nonsense is needed to give screenblank * a fighting chance of working. */ - + int cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) { @@ -567,8 +580,9 @@ 0, prot, BUS_SPACE_MAP_LINEAR)); } else if (off >= CG14_SXIO_VOFF && off < (CG14_SXIO_VOFF + 0x03ffffff)) { + off -= CG14_SXIO_VOFF; return (bus_space_mmap(sc->sc_sx->sc_tag, 0x800000000LL, - sc->sc_fb_paddr + (off - CG14_SXIO_VOFF), + sc->sc_fb_paddr + off, prot, BUS_SPACE_MAP_LINEAR)); #endif } else @@ -1204,20 +1218,20 @@ pptr = addr; cnt = wi; if (pre) { - sta(pptr & ~7, ASI_SX, SX_STBS(8, pre - 1, pptr & 7)); + sxm(SX_STBS, pptr, 8, pre - 1); pptr += pre; cnt -= pre; } /* now do the aligned pixels in 32bit chunks */ while(cnt > 3) { words = uimin(32, cnt >> 2); - sta(pptr & ~7, ASI_SX, SX_STS(8, words - 1, pptr & 7)); + sxm(SX_STS, pptr, 8, words - 1); pptr += words << 2; cnt -= words << 2; } /* do any remaining pixels byte-wise again */ if (cnt > 0) - sta(pptr & ~7, ASI_SX, SX_STBS(8, cnt - 1, pptr & 7)); + sxm(SX_STBS, pptr, 8, cnt - 1); addr += stride; } } @@ -1275,28 +1289,25 @@ for (line = 0; line < he; line++) { pptr = addr; /* load a whole scanline */ - sta(pptr & ~7, ASI_SX, SX_LD(8, words - 1, pptr & 7)); + sxm(SX_LD, pptr, 8, words - 1); reg = 8; if (pre) { cg14_set_mask(sc, lmask); - sx_write(sc->sc_sx, SX_INSTRUCTIONS, - SX_ROPB(8, 8, 40, 0)); + sxi(SX_ROPB, 8, 8, 40, 0); reg++; } if (cnt > 0) { cg14_set_mask(sc, 0xffffffff); /* XXX handle cnt > 16 */ - sx_write(sc->sc_sx, SX_INSTRUCTIONS, - SX_ROP(reg, reg, reg + 32, cnt - 1)); + sxi(SX_ROP, reg, reg, reg + 32, cnt - 1); reg += cnt; } if (post) { cg14_set_mask(sc, rmask); - sx_write(sc->sc_sx, SX_INSTRUCTIONS, - SX_ROPB(reg, 7, reg + 32, 0)); + sxi(SX_ROPB, reg, 7, reg + 32, 0); reg++; } - sta(pptr & ~7, ASI_SX, SX_ST(40, words - 1, pptr & 7)); + sxm(SX_ST, pptr, 40, words - 1); addr += stride; } } @@ -1307,7 +1318,7 @@ int num; while (cnt > 0) { num = uimin(32, cnt); - sta(addr & ~7, ASI_SX, SX_LD(reg, num - 1, addr & 7)); + sxm(SX_LD, addr, reg, num - 1); cnt -= num; reg += num; addr += (num << 2); @@ -1320,7 +1331,7 @@ int num; while (cnt > 0) { num = uimin(32, cnt); - sta(addr & ~7, ASI_SX, SX_ST(reg, num - 1, addr & 7)); + sxm(SX_ST, addr, reg, num - 1); cnt -= num; reg += num; addr += (num << 2); @@ -1355,10 +1366,8 @@ dptr = daddr; cnt = wi; if (pre > 0) { - sta(sptr & ~7, ASI_SX, - SX_LDB(32, pre - 1, sptr & 7)); - sta(dptr & ~7, ASI_SX, - SX_STB(32, pre - 1, dptr & 7)); + sxm(SX_LDB, sptr, 32, pre - 1); + sxm(SX_STB, dptr, 32, pre - 1); cnt -= pre; sptr += pre; dptr += pre; @@ -1373,10 +1382,8 @@ cnt -= num << 2; } if (cnt > 0) { - sta(sptr & ~7, ASI_SX, - SX_LDB(32, cnt - 1, sptr & 7)); - sta(dptr & ~7, ASI_SX, - SX_STB(32, cnt - 1, dptr & 7)); + sxm(SX_LDB, sptr, 32, cnt - 1); + sxm(SX_STB, dptr, 32, cnt - 1); } saddr += skip; daddr += skip; @@ -1389,17 +1396,15 @@ dptr = daddr; cnt = wi; while(cnt > 31) { - sta(sptr & ~7, ASI_SX, SX_LDB(32, 31, sptr & 7)); - sta(dptr & ~7, ASI_SX, SX_STB(32, 31, dptr & 7)); + sxm(SX_LDB, sptr, 32, 31); + sxm(SX_STB, dptr, 32, 31); sptr += 32; dptr += 32; cnt -= 32; } if (cnt > 0) { - sta(sptr & ~7, ASI_SX, - SX_LDB(32, cnt - 1, sptr & 7)); - sta(dptr & ~7, ASI_SX, - SX_STB(32, cnt - 1, dptr & 7)); + sxm(SX_LDB, sptr, 32, cnt - 1); + sxm(SX_STB, dptr, 32, cnt - 1); } saddr += skip; daddr += skip; @@ -1444,22 +1449,22 @@ for (line = 0; line < he; line++) { /* read source line, in all quads */ - sta(saddr & ~7, ASI_SX, SX_LDUQ0(8, swi - 1, saddr & 7)); + sxm(SX_LDUQ0, saddr, 8, swi - 1); /* now write it out */ dd = daddr; r = dreg; if (in > 0) { - sta(dd & ~7, ASI_SX, SX_STB(r, in - 1, dd & 7)); + sxm(SX_STB, dd, r, in - 1); dd += in; r += in; } if (q > 0) { - sta(dd & ~7, ASI_SX, SX_STUQ0(r, q - 1, dd & 7)); + sxm(SX_STUQ0, dd, r, q - 1); r += q << 2; dd += q << 2; } if (out > 0) { - sta(dd & ~7, ASI_SX, SX_STB(r, out - 1, dd & 7)); + sxm(SX_STB, dd, r, out - 1); } saddr += stride; daddr += stride; @@ -1518,7 +1523,7 @@ for (i = 0; i < he; i++) { reg = *data8; cg14_set_mask(sc, reg << 24); - sta(addr & ~7, ASI_SX, SX_STBS(8, wi - 1, addr & 7)); + sxm(SX_STBS, addr, 8, wi - 1); data8++; addr += stride; } @@ -1530,7 +1535,7 @@ for (i = 0; i < he; i++) { reg = *data16; cg14_set_mask(sc, reg << 16); - sta(addr & ~7, ASI_SX, SX_STBS(8, wi - 1, addr & 7)); + sxm(SX_STBS, addr, 8, wi - 1); data16++; addr += stride; } @@ -1679,20 +1684,20 @@ cnt = wi; if (in != 0) { in = 4 - in; /* pixels to write until aligned */ - sta(next & ~7, ASI_SX, SX_STB(8, in - 1, next & 7)); + sxm(SX_STB, next, 8, in - 1); next += in; reg = 8 + in; cnt -= in; } q = cnt >> 2; /* number of writes we can do in quads */ if (q > 0) { - sta(next & ~7, ASI_SX, SX_STUQ0(reg, q - 1, next & 7)); + sxm(SX_STUQ0, next, reg, q - 1); next += (q << 2); cnt -= (q << 2); reg += (q << 2); } if (cnt > 0) { - sta(next & ~7, ASI_SX, SX_STB(reg, cnt - 1, next & 7)); + sxm(SX_STB, next, reg, cnt - 1); } addr += stride; Index: src/sys/dev/wscons/wsdisplay_glyphcache.c diff -u src/sys/dev/wscons/wsdisplay_glyphcache.c:1.11 src/sys/dev/wscons/wsdisplay_glyphcache.c:1.12 --- src/sys/dev/wscons/wsdisplay_glyphcache.c:1.11 Mon Sep 3 16:29:34 2018 +++ src/sys/dev/wscons/wsdisplay_glyphcache.c Thu Jun 8 05:48:41 2023 @@ -53,17 +53,24 @@ static inline int attr2idx(long attr) { - if ((attr & 0xf0f0fff8) != 0) + if ((attr & 0xf0f00ff8) != 0) return -1; return (((attr >> 16) & 0x0f) | ((attr >> 20) & 0xf0)); } -/* first line, lines, width, attr */ int glyphcache_init(glyphcache *gc, int first, int lines, int width, int cellwidth, int cellheight, long attr) { + return glyphcache_init_align(gc, first, lines, width, cellwidth, cellheight, + attr, 0); +} + +int +glyphcache_init_align(glyphcache *gc, int first, int lines, int width, + int cellwidth, int cellheight, long attr, int alignment) +{ /* first the geometry stuff */ if (lines < 0) lines = 0; @@ -72,6 +79,7 @@ gc->gc_cellheight = -1; gc->gc_firstline = first; gc->gc_lines = lines; + gc->gc_cellalign = alignment; gc->gc_buckets = NULL; gc->gc_numbuckets = 0; // XXX: Never free? @@ -97,9 +105,16 @@ } gc->gc_cellwidth = cellwidth; + if (gc->gc_cellalign != 0) { + /* alignment in bytes */ + gc->gc_cellstride = + (gc->gc_cellwidth + gc->gc_cellalign - 1) & + ~(gc->gc_cellalign - 1); + } else + gc->gc_cellstride = cellwidth; gc->gc_cellheight = cellheight; - gc->gc_cellsperline = gc->gc_width / cellwidth; + gc->gc_cellsperline = gc->gc_width / gc->gc_cellstride; cache_lines = gc->gc_lines / cellheight; gc->gc_numcells = cache_lines * gc->gc_cellsperline; @@ -144,6 +159,8 @@ glyphcache_wipe(gc); DPRINTF("%s: using %d cells total, from %d width %d\n", __func__, gc->gc_numcells, gc->gc_firstline, gc->gc_cellsperline); + DPRINTF("%s: cell size %d x %d, stride %d\n", __func__, + gc->gc_cellwidth, gc->gc_cellheight, gc->gc_cellstride); return 0; } @@ -209,7 +226,7 @@ cell += b->gb_firstcell; cy = gc->gc_firstline + (cell / gc->gc_cellsperline) * gc->gc_cellheight; - cx = (cell % gc->gc_cellsperline) * gc->gc_cellwidth; + cx = (cell % gc->gc_cellsperline) * gc->gc_cellstride; b->gb_map[c - 33] = (cx << 16) | cy; gc->gc_bitblt(gc->gc_blitcookie, x, y, cx, cy, gc->gc_cellwidth, gc->gc_cellheight, gc->gc_rop); Index: src/sys/dev/wscons/wsdisplay_glyphcachevar.h diff -u src/sys/dev/wscons/wsdisplay_glyphcachevar.h:1.5 src/sys/dev/wscons/wsdisplay_glyphcachevar.h:1.6 --- src/sys/dev/wscons/wsdisplay_glyphcachevar.h:1.5 Fri Jun 2 19:30:10 2017 +++ src/sys/dev/wscons/wsdisplay_glyphcachevar.h Thu Jun 8 05:48:41 2023 @@ -45,6 +45,8 @@ /* geometry */ int gc_numcells; int gc_cellwidth; + int gc_cellstride; + int gc_cellalign; int gc_cellheight; int gc_cellsperline; int gc_firstline; /* first line in vram to use for glyphs */ @@ -71,6 +73,9 @@ /* first line, lines, width, cellwidth, cellheight, attr */ int glyphcache_init(glyphcache *, int, int, int, int, int, long); +/* first line, lines, width, cellwidth, cellheight, attr, alignment */ +int glyphcache_init_align(glyphcache *, int, int, int, int, int, long, int); + /* adapt to changed font */ int glyphcache_reconfig(glyphcache *, int, int, long); Index: src/sys/arch/sparc/dev/sx.c diff -u src/sys/arch/sparc/dev/sx.c:1.6 src/sys/arch/sparc/dev/sx.c:1.7 --- src/sys/arch/sparc/dev/sx.c:1.6 Thu Apr 13 13:07:48 2023 +++ src/sys/arch/sparc/dev/sx.c Tue Jun 13 10:09:31 2023 @@ -84,6 +84,7 @@ sc->sc_dev = self; sc->sc_tag = ma->ma_bustag; sc->sc_uregs = ma->ma_paddr + 0x1000; + sc->sc_cnt = 0; if (bus_space_map(sc->sc_tag, ma->ma_paddr, 0x1000, 0, &sc->sc_regh)) { aprint_error_dev(self, "failed to map registers\n"); Index: src/sys/arch/sparc/dev/sxvar.h diff -u src/sys/arch/sparc/dev/sxvar.h:1.4 src/sys/arch/sparc/dev/sxvar.h:1.5 --- src/sys/arch/sparc/dev/sxvar.h:1.4 Fri Mar 1 02:30:42 2019 +++ src/sys/arch/sparc/dev/sxvar.h Tue Jun 13 10:09:31 2023 @@ -32,11 +32,14 @@ #ifndef SXVAR_H #define SXVAR_H +#include + struct sx_softc { device_t sc_dev; bus_addr_t sc_uregs; bus_space_tag_t sc_tag; bus_space_handle_t sc_regh; + int sc_cnt; }; static inline void @@ -51,6 +54,26 @@ return bus_space_read_4(sc->sc_tag, sc->sc_regh, addr); } +/* + * to be used before issuing SX instructions + * this will periodically allow the instruction queue to drain in order + * to avoid excessive MBus relinquish & retry cycles during long SX ops + * which may cause us to lose interrupts + */ +static inline void +sx_wait(struct sx_softc *sc) +{ + uint32_t reg; + if (sc->sc_cnt > 6) { + do { + reg = bus_space_read_4(sc->sc_tag, sc->sc_regh, + SX_CONTROL_STATUS); + } while ((reg & SX_MT) == 0); + sc->sc_cnt = 0; + } else + sc->sc_cnt++; +} + void sx_dump(void); #endif Index: src/sys/arch/sparc/dev/cgfourteen.c diff -u src/sys/arch/sparc/dev/cgfourteen.c:1.94 src/sys/arch/sparc/dev/cgfourteen.c:1.95 --- src/sys/arch/sparc/dev/cgfourteen.c:1.94 Tue May 23 10:20:12 2023 +++ src/sys/arch/sparc/dev/cgfourteen.c Tue Jun 13 10:11:17 2023 @@ -173,7 +173,9 @@ * issue ALU instruction: * sxi(OPCODE, srcA, srcB, dest, count) */ -#define sxi(inst, a, b, d, cnt) sx_write(sc->sc_sx, SX_INSTRUCTIONS, inst((a), (b), (d), (cnt))) +#define sxi(inst, a, b, d, cnt) \ + sx_wait(sc->sc_sx); \ + sx_write(sc->sc_sx, SX_INSTRUCTIONS, inst((a), (b), (d), (cnt))) /* * issue memory referencing instruction: @@ -770,13 +772,13 @@ sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; sc->sc_defaultscreen_descr.nrows = ri->ri_rows; sc->sc_defaultscreen_descr.ncols = ri->ri_cols; - glyphcache_init(&sc->sc_gc, sc->sc_fb.fb_type.fb_height + 5, + glyphcache_init_align(&sc->sc_gc, sc->sc_fb.fb_type.fb_height + 5, (sc->sc_vramsize / sc->sc_fb.fb_type.fb_width) - sc->sc_fb.fb_type.fb_height - 5, sc->sc_fb.fb_type.fb_width, ri->ri_font->fontwidth, ri->ri_font->fontheight, - defattr); + defattr, 4); if (is_cons) { wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, defattr); Index: src/sys/dev/sbus/mgx.c diff -u src/sys/dev/sbus/mgx.c:1.20 src/sys/dev/sbus/mgx.c:1.21 --- src/sys/dev/sbus/mgx.c:1.20 Thu Nov 11 19:37:30 2021 +++ src/sys/dev/sbus/mgx.c Wed Jun 28 08:11:52 2023 @@ -342,7 +342,7 @@ * leave some room between visible screen and glyph cache for upload * buffers used by putchar_mono() */ - bsize = (32 * 1024 * sc->sc_stride - 1) / sc->sc_stride; + bsize = (32 * 1024 + sc->sc_stride - 1) / sc->sc_stride; glyphcache_init(&sc->sc_gc, sc->sc_height + bsize, (0x400000 / sc->sc_stride) - (sc->sc_height + bsize), Index: src/sys/dev/sbus/mgx.c diff -u src/sys/dev/sbus/mgx.c:1.21 src/sys/dev/sbus/mgx.c:1.22 --- src/sys/dev/sbus/mgx.c:1.21 Wed Jun 28 08:11:52 2023 +++ src/sys/dev/sbus/mgx.c Wed Jun 28 08:53:43 2023 @@ -666,7 +666,8 @@ dec = sc->sc_dec; dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) | (DEC_START_DIMX << DEC_START_SHIFT); - mgx_wait_fifo(sc, 5); + //mgx_wait_fifo(sc, 5); + mgx_wait_engine(sc); mgx_write_1(sc, ATR_ROP, ROP_SRC); mgx_write_4(sc, ATR_FG, col); mgx_write_4(sc, ATR_DEC, dec); Index: src/sys/dev/sbus/mgx.c diff -u src/sys/dev/sbus/mgx.c:1.22 src/sys/dev/sbus/mgx.c:1.23 --- src/sys/dev/sbus/mgx.c:1.22 Wed Jun 28 08:53:43 2023 +++ src/sys/dev/sbus/mgx.c Wed Jun 28 11:08:47 2023 @@ -80,7 +80,7 @@ int sc_fbsize; int sc_mode; char sc_name[8]; - uint32_t sc_dec; + uint32_t sc_dec, sc_r_dec, sc_r_fg; u_char sc_cmap_red[256]; u_char sc_cmap_green[256]; u_char sc_cmap_blue[256]; @@ -216,6 +216,24 @@ bus_space_write_4(sc->sc_tag, sc->sc_blith, reg, val); } +static inline void +mgx_set_dec(struct mgx_softc *sc, uint32_t dec) +{ + if (dec == sc->sc_r_dec) return; + sc->sc_r_dec = dec; + mgx_wait_engine(sc); + mgx_write_4(sc, ATR_DEC, dec); +} + +static inline void +mgx_set_fg(struct mgx_softc *sc, uint32_t fg) +{ + if (fg == sc->sc_r_fg) return; + sc->sc_r_fg = fg; + mgx_wait_fifo(sc, 1); + mgx_write_4(sc, ATR_FG, fg); +} + static int mgx_match(device_t parent, cfdata_t cf, void *aux) { @@ -531,6 +549,8 @@ int i; uint8_t reg; + sc->sc_r_dec = 0xffffffff; + sc->sc_r_fg = 0x12345678; /* wait for everything to go idle */ if (mgx_wait_engine(sc) == 0) return; @@ -643,9 +663,9 @@ yd += he - 1; dec |= DEC_DIR_Y_REVERSE; } - mgx_wait_fifo(sc, 5); + mgx_set_dec(sc, dec); + mgx_wait_fifo(sc, 4); mgx_write_1(sc, ATR_ROP, rop); - mgx_write_4(sc, ATR_DEC, dec); mgx_write_4(sc, ATR_SRC_XY, (ys << 16) | xs); mgx_write_4(sc, ATR_DST_XY, (yd << 16) | xd); mgx_write_4(sc, ATR_WH, (he << 16) | wi); @@ -666,11 +686,10 @@ dec = sc->sc_dec; dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) | (DEC_START_DIMX << DEC_START_SHIFT); - //mgx_wait_fifo(sc, 5); - mgx_wait_engine(sc); + mgx_set_dec(sc, dec); + mgx_set_fg(sc, col); + mgx_wait_fifo(sc, 3); mgx_write_1(sc, ATR_ROP, ROP_SRC); - mgx_write_4(sc, ATR_FG, col); - mgx_write_4(sc, ATR_DEC, dec); mgx_write_4(sc, ATR_DST_XY, (y << 16) | x); mgx_write_4(sc, ATR_WH, (he << 16) | wi); } @@ -754,8 +773,8 @@ return; } - mgx_wait_fifo(sc, 3); - mgx_write_4(sc, ATR_FG, ri->ri_devcmap[fg]); + mgx_set_fg(sc, ri->ri_devcmap[fg]); + mgx_wait_fifo(sc, 2); mgx_write_4(sc, ATR_BG, ri->ri_devcmap[bg]); mgx_write_1(sc, ATR_ROP, ROP_SRC); @@ -790,10 +809,10 @@ for (i = 0; i < ri->ri_fontscale; i++) d[i] = s[i]; } - mgx_wait_fifo(sc, 5); - mgx_write_4(sc, ATR_DEC, sc->sc_dec | (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) | + mgx_set_dec(sc, sc->sc_dec | (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) | (DEC_START_DIMX << DEC_START_SHIFT) | DEC_SRC_LINEAR | DEC_SRC_CONTIGUOUS | DEC_MONOCHROME); + mgx_wait_fifo(sc, 3); mgx_write_4(sc, ATR_SRC_XY, ((scratch & 0xfff000) << 4) | (scratch & 0xfff)); mgx_write_4(sc, ATR_DST_XY, (y << 16) | x); mgx_write_4(sc, ATR_WH, (he << 16) | wi);