Module Name:    src
Committed By:   macallan
Date:           Wed Feb 28 10:25:36 UTC 2024

Modified Files:
        src/sys/arch/hppa/dev: gftfb.c

Log Message:
add hardware cursor support, mostly for X


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/hppa/dev/gftfb.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/hppa/dev/gftfb.c
diff -u src/sys/arch/hppa/dev/gftfb.c:1.6 src/sys/arch/hppa/dev/gftfb.c:1.7
--- src/sys/arch/hppa/dev/gftfb.c:1.6	Wed Feb 21 13:24:40 2024
+++ src/sys/arch/hppa/dev/gftfb.c	Wed Feb 28 10:25:36 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: gftfb.c,v 1.6 2024/02/21 13:24:40 macallan Exp $	*/
+/*	$NetBSD: gftfb.c,v 1.7 2024/02/28 10:25:36 macallan Exp $	*/
 
 /*	$OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $	*/
 
@@ -29,6 +29,7 @@
 #include <sys/systm.h>
 #include <sys/kmem.h>
 #include <sys/device.h>
+#include <sys/mutex.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
@@ -82,10 +83,15 @@ struct	gftfb_softc {
 	u_char sc_cmap_red[256];
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];
+	kmutex_t sc_hwlock;
 	uint32_t sc_hwmode;
 #define HW_FB	0
 #define HW_FILL	1
 #define HW_BLIT	2
+	/* cursor stuff */
+	int sc_cursor_x, sc_cursor_y;
+	int sc_hot_x, sc_hot_y, sc_enabled;
+	uint32_t sc_pos;
 	glyphcache sc_gc;
 };
 
@@ -139,6 +145,9 @@ static void	gftfb_erasecols(void *, int,
 static void	gftfb_copyrows(void *, int, int, int);
 static void	gftfb_eraserows(void *, int, int, long);
 
+static void	gftfb_move_cursor(struct gftfb_softc *, int, int);
+static int	gftfb_do_cursor(struct gftfb_softc *, struct wsdisplay_cursor *);
+
 struct wsdisplay_accessops gftfb_accessops = {
 	gftfb_ioctl,
 	gftfb_mmap,
@@ -175,6 +184,8 @@ struct wsdisplay_accessops gftfb_accesso
 #define	    MaskDynamic	    1	/* Mask register reloaded by direct access */
 #define	    MaskOtc	    0	/* Mask contains Object Count valid bits */
 
+static inline void gftfb_wait_fifo(struct gftfb_softc *, uint32_t);
+
 int
 gftfb_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -209,6 +220,9 @@ gftfb_attach(device_t parent, device_t s
 	sc->sc_base.sc_enable_rom = gftfb_enable_rom;
 	sc->sc_base.sc_disable_rom = gftfb_disable_rom;
 
+	/* we can *not* be interrupted when doing colour map accesses */
+	mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH);
+
 	aprint_normal("\n");
 
 	if (gftfb_check_rom(sc, paa) != 0)
@@ -663,8 +677,12 @@ gftfb_setup(struct gftfb_softc *sc)
 	struct sti_rom *rom = sc->sc_base.sc_rom;
 	bus_space_tag_t memt = rom->memt;
 	bus_space_handle_t memh = rom->regh[2];
+	int i;	
 
 	sc->sc_hwmode = HW_FB;
+	sc->sc_hot_x = 0;
+	sc->sc_hot_y = 0;
+	sc->sc_enabled = 0;
 
 	/* set Bt458 read mask register to all planes */
 	gftfb_wait(sc);
@@ -702,6 +720,50 @@ gftfb_setup(struct gftfb_softc *sc)
 	    bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
 	bus_space_write_stream_4(memt, memh, NGLE_REG_27,
 	    bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
+
+	/* initialize cursor sprite */
+	gftfb_wait(sc);
+	
+	/* cursor mask */
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A07000);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+	for (i = 0; i < 64; i++) {
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0xffffffff);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_5, 0xffffffff);
+	}
+
+	/* cursor image */
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A06000);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+	for (i = 0; i < 64; i++) {
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0xff00ff00);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_5, 0xff00ff00);
+	}
+
+	/* colour map */
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xBBE0F000);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0x000000ff);	/* BG */
+	bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0x00ff0000);	/* FG */
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80008004);
+	gftfb_setup_fb(sc);	
+
+	gftfb_move_cursor(sc, 100, 100);
+
 }
 
 static int
@@ -773,7 +835,41 @@ gftfb_ioctl(void *v, void *vs, u_long cm
 
 		return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
 	}
+
+	case WSDISPLAYIO_GCURPOS:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			cp->x = sc->sc_cursor_x;
+			cp->y = sc->sc_cursor_y;
+		}
+		return 0;
+
+	case WSDISPLAYIO_SCURPOS:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			gftfb_move_cursor(sc, cp->x, cp->y);
+		}
+		return 0;
+
+	case WSDISPLAYIO_GCURMAX:
+		{
+			struct wsdisplay_curpos *cp = (void *)data;
+
+			cp->x = 64;
+			cp->y = 64;
+		}
+		return 0;
+
+	case WSDISPLAYIO_SCURSOR:
+		{
+			struct wsdisplay_cursor *cursor = (void *)data;
+
+			return gftfb_do_cursor(sc, cursor);
+		}
 	}
+
 	return EPASSTHROUGH;
 }
 
@@ -909,6 +1005,7 @@ gftfb_putpalreg(struct gftfb_softc *sc, 
 	bus_space_tag_t memt = rom->memt;
 	bus_space_handle_t memh = rom->regh[2];
 
+	mutex_enter(&sc->sc_hwlock);
 	gftfb_wait(sc);
 	bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
 	bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
@@ -923,6 +1020,7 @@ gftfb_putpalreg(struct gftfb_softc *sc, 
 	bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
 	bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80000100);
 	gftfb_setup_fb(sc);
+	mutex_exit(&sc->sc_hwlock);
 	return 0;
 }
 
@@ -1187,3 +1285,182 @@ gftfb_eraserows(void *cookie, int row, i
 			ri->ri_flg &= ~RI_CURSOR;
 	}
 }
+
+/*
+ * cursor sprite handling
+ * like most hw info, xf86 3.3 -> nglehdw.h was used as documentation
+ * problem is, the PCI EG doesn't quite behave like an S9000_ID_ARTIST
+ * the cursor position register bahaves like the one on HCRX while using
+ * the same address as Artist, incuding the enable bit and weird handling
+ * of negative coordinates. The rest of it, colour map, sprite image etc.,
+ * behave like Artist.
+ */
+ 
+static void
+gftfb_move_cursor(struct gftfb_softc *sc, int x, int y)
+{
+	struct sti_rom *rom = sc->sc_base.sc_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+	uint32_t pos;
+
+	sc->sc_cursor_x = x;
+	x -= sc->sc_hot_x;
+	sc->sc_cursor_y = y;
+	y -= sc->sc_hot_y;
+
+	if (x < 0) x = 0x1000 - x;
+	if (y < 0) y = 0x1000 - y;
+	pos = (x << 16) | y;
+	if (sc->sc_enabled) pos |= 0x80000000;
+	gftfb_wait(sc);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_17, pos);
+	bus_space_write_stream_4(memt, memh, NGLE_REG_18, 0x80);
+}
+
+static int
+gftfb_do_cursor(struct gftfb_softc *sc, struct wsdisplay_cursor *cur)
+{
+	struct sti_rom *rom = sc->sc_base.sc_rom;
+	bus_space_tag_t memt = rom->memt;
+	bus_space_handle_t memh = rom->regh[2];
+
+	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
+
+		sc->sc_enabled = cur->enable;
+		cur->which |= WSDISPLAY_CURSOR_DOPOS;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
+
+		sc->sc_hot_x = cur->hot.x;
+		sc->sc_hot_y = cur->hot.y;
+		cur->which |= WSDISPLAY_CURSOR_DOPOS;
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
+
+		gftfb_move_cursor(sc, cur->pos.x, cur->pos.y);
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
+		uint32_t rgb;
+		uint8_t r[2], g[2], b[2];
+
+		copyin(cur->cmap.blue, b, 2);
+		copyin(cur->cmap.green, g, 2);
+		copyin(cur->cmap.red, r, 2);
+		mutex_enter(&sc->sc_hwlock);
+		gftfb_wait(sc);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xBBE0F000);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+		gftfb_wait(sc);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, 0);
+		rgb = (r[0] << 16) | (g[0] << 8) | b[0];
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, rgb);	/* BG */
+		rgb = (r[1] << 16) | (g[1] << 8) | b[1];
+		bus_space_write_stream_4(memt, memh, NGLE_REG_4, rgb);	/* FG */
+		bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_26, 0x80008004);
+		gftfb_setup_fb(sc);	
+		mutex_exit(&sc->sc_hwlock);
+
+	}
+	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
+		uint32_t buffer[128], latch, tmp;
+		int i;
+
+		copyin(cur->mask, buffer, 512);
+		gftfb_wait(sc);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A07000);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+		for (i = 0; i < 128; i += 2) {
+			latch = 0;
+			tmp = buffer[i] & 0x80808080;
+			latch |= tmp >> 7;
+			tmp = buffer[i] & 0x40404040;
+			latch |= tmp >> 5;
+			tmp = buffer[i] & 0x20202020;
+			latch |= tmp >> 3;
+			tmp = buffer[i] & 0x10101010;
+			latch |= tmp >> 1;
+			tmp = buffer[i] & 0x08080808;
+			latch |= tmp << 1;
+			tmp = buffer[i] & 0x04040404;
+			latch |= tmp << 3;
+			tmp = buffer[i] & 0x02020202;
+			latch |= tmp << 5;
+			tmp = buffer[i] & 0x01010101;
+			latch |= tmp << 7;
+			bus_space_write_stream_4(memt, memh, NGLE_REG_4, latch);
+			latch = 0;
+			tmp = buffer[i + 1] & 0x80808080;
+			latch |= tmp >> 7;
+			tmp = buffer[i + 1] & 0x40404040;
+			latch |= tmp >> 5;
+			tmp = buffer[i + 1] & 0x20202020;
+			latch |= tmp >> 3;
+			tmp = buffer[i + 1] & 0x10101010;
+			latch |= tmp >> 1;
+			tmp = buffer[i + 1] & 0x08080808;
+			latch |= tmp << 1;
+			tmp = buffer[i + 1] & 0x04040404;
+			latch |= tmp << 3;
+			tmp = buffer[i + 1] & 0x02020202;
+			latch |= tmp << 5;
+			tmp = buffer[i + 1] & 0x01010101;
+			latch |= tmp << 7;
+			bus_space_write_stream_4(memt, memh, NGLE_REG_5, latch);
+		}
+
+		copyin(cur->image, buffer, 512);
+		gftfb_wait(sc);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x300);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x28A06000);
+		bus_space_write_stream_4(memt, memh, NGLE_REG_3, 0);
+		for (i = 0; i < 128; i += 2) {
+			latch = 0;
+			tmp = buffer[i] & 0x80808080;
+			latch |= tmp >> 7;
+			tmp = buffer[i] & 0x40404040;
+			latch |= tmp >> 5;
+			tmp = buffer[i] & 0x20202020;
+			latch |= tmp >> 3;
+			tmp = buffer[i] & 0x10101010;
+			latch |= tmp >> 1;
+			tmp = buffer[i] & 0x08080808;
+			latch |= tmp << 1;
+			tmp = buffer[i] & 0x04040404;
+			latch |= tmp << 3;
+			tmp = buffer[i] & 0x02020202;
+			latch |= tmp << 5;
+			tmp = buffer[i] & 0x01010101;
+			latch |= tmp << 7;
+			bus_space_write_stream_4(memt, memh, NGLE_REG_4, latch);
+			latch = 0;
+			tmp = buffer[i + 1] & 0x80808080;
+			latch |= tmp >> 7;
+			tmp = buffer[i + 1] & 0x40404040;
+			latch |= tmp >> 5;
+			tmp = buffer[i + 1] & 0x20202020;
+			latch |= tmp >> 3;
+			tmp = buffer[i + 1] & 0x10101010;
+			latch |= tmp >> 1;
+			tmp = buffer[i + 1] & 0x08080808;
+			latch |= tmp << 1;
+			tmp = buffer[i + 1] & 0x04040404;
+			latch |= tmp << 3;
+			tmp = buffer[i + 1] & 0x02020202;
+			latch |= tmp << 5;
+			tmp = buffer[i + 1] & 0x01010101;
+			latch |= tmp << 7;
+			bus_space_write_stream_4(memt, memh, NGLE_REG_5, latch);
+		}
+		gftfb_setup_fb(sc);
+	}
+
+	return 0;
+}

Reply via email to