Module Name:    src
Committed By:   tsutsui
Date:           Wed May  1 19:28:33 UTC 2024

Modified Files:
        src/sys/arch/hp300/dev: diofb.c diofbvar.h topcat.c

Log Message:
Fix topcat(4) problems on some models that cause garbages on screen.

- Make sure that windowmove (hardware BITBLT) ops complete by checking
  tc_busywait() before calling putchar functions by MI rasops(9).
  It looks CPU accesses against VRAM during windowmove (copy, erase,
  and cursor) ops causes unexpected garbages at least on 98543 on HP360,
  98547 on HP370, and also on 98543 on 040 HP380 (but not on 98549).

- Handle 'sparse VRAM' on 98543 (and probably 98542) properly:
 - Prepare and use own topcat_putchar1_4() function for sparse VRAM.
 - Pass proper 'VRAM width' rather than actuall font width to all
   windowmove (copycols, erasecols, copyrows, eraserows, and do_cursor)
   operation functions.

Now all topcat(4) consoles on 98543 on HP360/HP380 and 98547 on HP370
work fine, and no visible regression on 98549 on HP380 and 98544 on HP360.

Worth to pullup netbsd-10.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/hp300/dev/diofb.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/hp300/dev/diofbvar.h
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/hp300/dev/topcat.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/hp300/dev/diofb.c
diff -u src/sys/arch/hp300/dev/diofb.c:1.9 src/sys/arch/hp300/dev/diofb.c:1.10
--- src/sys/arch/hp300/dev/diofb.c:1.9	Mon Apr 29 17:25:11 2024
+++ src/sys/arch/hp300/dev/diofb.c	Wed May  1 19:28:33 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: diofb.c,v 1.9 2024/04/29 17:25:11 tsutsui Exp $	*/
+/*	$NetBSD: diofb.c,v 1.10 2024/05/01 19:28:33 tsutsui Exp $	*/
 /*	$OpenBSD: diofb.c,v 1.18 2010/12/26 15:40:59 miod Exp $	*/
 
 /*
@@ -361,10 +361,11 @@ diofb_copycols(void *cookie, int row, in
 {
 	struct rasops_info *ri = cookie;
 	struct diofb *fb = ri->ri_hw;
+	int fontwidth = fb->wsd.fontwidth;
 
-	n *= ri->ri_font->fontwidth;
-	src *= ri->ri_font->fontwidth;
-	dst *= ri->ri_font->fontwidth;
+	n *= fontwidth;
+	src *= fontwidth;
+	dst *= fontwidth;
 	row *= ri->ri_font->fontheight;
 
 	(*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
@@ -394,11 +395,12 @@ diofb_erasecols(void *cookie, int row, i
 	struct diofb *fb = ri->ri_hw;
 	int fg, bg;
 	int snum, scol, srow;
+	int fontwidth = fb->wsd.fontwidth;
 
 	rasops_unpack_attr(attr, &fg, &bg, NULL);
 
-	snum = num * ri->ri_font->fontwidth;
-	scol = col * ri->ri_font->fontwidth + ri->ri_xorigin;
+	snum = num * fontwidth;
+	scol = col * fontwidth + ri->ri_xorigin;
 	srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
 
 	/*
@@ -423,7 +425,7 @@ diofb_eraserows(void *cookie, int row, i
 	bg ^= 0xff;
 
 	if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
-		rc = (*fb->bmv)(fb, 0, 0, 0, 0, ri->ri_width, ri->ri_height,
+		rc = (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, ri->ri_height,
 		    RR_CLEAR, bg);
 	} else {
 		srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
@@ -440,10 +442,11 @@ diofb_do_cursor(struct rasops_info *ri)
 {
 	struct diofb *fb = ri->ri_hw;
 	int x, y;
+	int fontwidth = fb->wsd.fontwidth;
 
-	x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
+	x = ri->ri_ccol * fontwidth + ri->ri_xorigin;
 	y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
-	(*fb->bmv)(fb, x, y, x, y, ri->ri_font->fontwidth,
+	(*fb->bmv)(fb, x, y, x, y, fontwidth,
 	    ri->ri_font->fontheight, RR_INVERT, 0xff);
 }
 

Index: src/sys/arch/hp300/dev/diofbvar.h
diff -u src/sys/arch/hp300/dev/diofbvar.h:1.4 src/sys/arch/hp300/dev/diofbvar.h:1.5
--- src/sys/arch/hp300/dev/diofbvar.h:1.4	Sun Jan 15 06:19:45 2023
+++ src/sys/arch/hp300/dev/diofbvar.h	Wed May  1 19:28:33 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: diofbvar.h,v 1.4 2023/01/15 06:19:45 tsutsui Exp $	*/
+/*	$NetBSD: diofbvar.h,v 1.5 2024/05/01 19:28:33 tsutsui Exp $	*/
 /*	$OpenBSD: diofbvar.h,v 1.10 2006/08/11 18:33:13 miod Exp $	*/
 
 /*
@@ -105,6 +105,9 @@ struct diofb {
 	/* blockmove routine */
 	int	(*bmv)(struct diofb *, uint16_t, uint16_t, uint16_t,
 		    uint16_t, uint16_t, uint16_t, int16_t, int16_t);
+
+	/* putchar routine to handle rasops; MD busywait might be required */
+	void	(*wsputchar)(void *, int, int, u_int, long);
 };
 
 /* Replacement Rules (rops) */

Index: src/sys/arch/hp300/dev/topcat.c
diff -u src/sys/arch/hp300/dev/topcat.c:1.10 src/sys/arch/hp300/dev/topcat.c:1.11
--- src/sys/arch/hp300/dev/topcat.c:1.10	Wed May  1 08:58:34 2024
+++ src/sys/arch/hp300/dev/topcat.c	Wed May  1 19:28:33 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: topcat.c,v 1.10 2024/05/01 08:58:34 tsutsui Exp $	*/
+/*	$NetBSD: topcat.c,v 1.11 2024/05/01 19:28:33 tsutsui Exp $	*/
 /*	$OpenBSD: topcat.c,v 1.15 2006/08/11 18:33:13 miod Exp $	*/
 
 /*
@@ -149,6 +149,8 @@ static int	topcat_windowmove(struct diof
 		    uint16_t, uint16_t, uint16_t, int16_t, int16_t);
 
 static int	topcat_ioctl(void *, void *, u_long, void *, int, struct lwp *);
+static void	topcat_putchar8(void *, int, int, u_int, long);
+static void	topcat_putchar1_4(void *, int, int, u_int, long);
 
 static struct wsdisplay_accessops topcat_accessops = {
 	topcat_ioctl,
@@ -312,8 +314,10 @@ int
 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr)
 {
 	volatile struct tcboxfb *tc = (struct tcboxfb *)fbr;
+	struct rasops_info *ri = &fb->ri;
 	int rc;
 	u_int i;
+	bool sparse = false;
 
 	if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0)
 		return rc;
@@ -355,11 +359,23 @@ topcat_reset(struct diofb *fb, int scode
 	 */
 	if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) {
 		fb->dwidth = 512;
+		sparse = true;
 	}
 
 	fb->bmv = topcat_windowmove;
 	topcat_restore(fb);
 	diofb_fbsetup(fb);
+	if (!sparse) {
+		/* save original rasops putchar op */
+		fb->wsputchar = ri->ri_ops.putchar;
+		ri->ri_ops.putchar = topcat_putchar8;
+	} else {
+		ri->ri_ops.putchar = topcat_putchar1_4;
+		/* copycols and erasecols ops require byte size of fontwidth */
+		fb->wsd.fontwidth *= 2;
+		/* copyrows and eraserows ops require byte size per line */
+		ri->ri_emuwidth *= 2;
+	}
 	for (i = 0; i <= fb->planemask; i++)
 		topcat_setcolor(fb, i);
 
@@ -549,6 +565,104 @@ topcat_windowmove(struct diofb *fb, uint
 	return 0;
 }
 
+static void
+topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr)
+{
+	struct rasops_info *ri = (struct rasops_info *)cookie;
+	struct diofb *diofb = ri->ri_hw;
+	volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva;
+
+	/* Wait windowmove ops complete before drawing a glyph */
+	tc_waitbusy(tc, diofb->planemask);
+
+	/* Call the original rasops putchar */
+	(*diofb->wsputchar)(cookie, row, col, uc, attr);
+}
+
+/*
+ * Put a single character on 1 bpp or 4 bpp variants with sparse VRAM addresses
+ */
+static void
+topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr)
+{
+	int width, height, cnt, fs;
+	uint32_t fb;
+	uint8_t *fr, clr[2];
+	uint8_t *dp, *rp;
+	struct rasops_info *ri;
+	struct diofb *diofb;
+	volatile struct tcboxfb *tc;
+
+	ri = (struct rasops_info *)cookie;
+
+	if (!CHAR_IN_FONT(uc, ri->ri_font))
+		return;
+
+	rp = ri->ri_bits + (row * ri->ri_yscale) +
+	    (col * ri->ri_xscale * 2);
+
+	height = ri->ri_font->fontheight;
+	width = ri->ri_font->fontwidth;
+	clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf];
+	clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf];
+
+	/* Wait windowmove ops complete before drawing a glyph */
+	diofb = ri->ri_hw;
+	tc = (struct tcboxfb *)diofb->regkva;
+	tc_waitbusy(tc, diofb->planemask);
+
+	/*
+	 * At least HP98543 requires to write 4 bpp data onto
+	 * both odd and even addresses.
+	 */
+	if (uc == ' ') {
+		uint16_t c = clr[0];
+
+		c = c << 8 | c;
+		while (height--) {
+			dp = rp;
+			rp += ri->ri_stride;
+
+			for (cnt = width; cnt; cnt--) {
+				*(uint16_t *)dp = c;
+				dp += 2;
+			}
+		}
+	} else {
+		uc -= ri->ri_font->firstchar;
+		fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale;
+		fs = ri->ri_font->stride;
+
+		while (height--) {
+			dp = rp;
+			fb = be32dec(fr);
+			fr += fs;
+			rp += ri->ri_stride;
+
+			for (cnt = width; cnt; cnt--) {
+				uint16_t c = clr[(fb >> 31) & 1];
+
+				c = c << 8 | c;
+				*(uint16_t *)dp = c;
+				dp += 2;
+				fb <<= 1;
+			}
+		}
+	}
+
+	/* Do underline */
+	if ((attr & WSATTR_UNDERLINE) != 0) {
+		uint16_t c = clr[1];
+
+		c = c << 8 | c;
+		rp -= ri->ri_stride * ri->ri_ul.off;
+
+		while (width--) {
+			*(uint16_t *)rp = c;
+			rp += 2;
+		}
+	}
+}
 
 /*
  *   Topcat/catseye console attachment

Reply via email to