Module Name:    src
Committed By:   macallan
Date:           Wed Oct  9 01:28:33 UTC 2013

Modified Files:
        src/sys/dev/pci: gffb.c

Log Message:
add hardware acceleration
For now this supports only GeForce2 MX cards but most NV1x chips should work
once their PCI iDs are added to gffb_match()
Tested only on macppc.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pci/gffb.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/dev/pci/gffb.c
diff -u src/sys/dev/pci/gffb.c:1.2 src/sys/dev/pci/gffb.c:1.3
--- src/sys/dev/pci/gffb.c:1.2	Wed Oct  2 16:35:38 2013
+++ src/sys/dev/pci/gffb.c	Wed Oct  9 01:28:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: gffb.c,v 1.2 2013/10/02 16:35:38 macallan Exp $	*/
+/*	$NetBSD: gffb.c,v 1.3 2013/10/09 01:28:33 macallan Exp $	*/
 
 /*
  * Copyright (c) 2007, 2012 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gffb.c,v 1.2 2013/10/02 16:35:38 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gffb.c,v 1.3 2013/10/09 01:28:33 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -96,6 +96,9 @@ struct gffb_softc {
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];
 	int sc_put, sc_current, sc_free;
+	uint32_t sc_rop;
+	void (*sc_putchar)(void *, int, int, u_int, long);
+	kmutex_t sc_lock;
 	glyphcache sc_gc;
 };
 
@@ -119,22 +122,20 @@ static int 	gffb_putpalreg(struct gffb_s
 static void	gffb_init(struct gffb_softc *);
 
 static void	gffb_make_room(struct gffb_softc *, int);
+static void	gffb_sync(struct gffb_softc *);
 
-#if notyet
-static void	gffb_flush_engine(struct gffb_softc *);
 static void	gffb_rectfill(struct gffb_softc *, int, int, int, int,
 			    uint32_t);
 static void	gffb_bitblt(void *, int, int, int, int, int,
 			    int, int);
+static void	gffb_rop(struct gffb_softc *, int);
 
 static void	gffb_cursor(void *, int, int, int);
 static void	gffb_putchar(void *, int, int, u_int, long);
-static void	gffb_putchar_aa(void *, int, int, u_int, long);
 static void	gffb_copycols(void *, int, int, int, int);
 static void	gffb_erasecols(void *, int, int, int, long);
 static void	gffb_copyrows(void *, int, int, int);
 static void	gffb_eraserows(void *, int, int, long);
-#endif /* notyet */
 
 struct wsdisplay_accessops gffb_accessops = {
 	gffb_ioctl,
@@ -198,7 +199,7 @@ gffb_attach(device_t parent, device_t se
 
 #ifdef GLYPHCACHE_DEBUG
 	/* leave some visible VRAM unused so we can see the glyph cache */
-	sc->sc_height -= 200;
+	sc->sc_height -= 300;
 #endif
 
 	if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) {
@@ -243,54 +244,59 @@ gffb_attach(device_t parent, device_t se
 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
 	sc->sc_locked = 0;
 
-	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
-	    &gffb_accessops);
-	sc->vd.init_screen = gffb_init_screen;
-
 	sc->sc_vramsize = bus_space_read_4(sc->sc_memt, sc->sc_regh,
 	    GFFB_VRAM) & 0xfff00000;
 
 	printf("vram: %d MB\n", sc->sc_vramsize >> 20);
+#ifdef GFFB_DEBUG
 	printf("put: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT));
 	printf("get: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET));
-	/* init engine here */
+#endif
+
+	/*
+	 * we don't have hardware synchronization so we need a lock to serialize
+	 * access to the DMA buffer between normal and kernel output
+	 * actually it might be enough to use atomic ops on sc_current, sc_free
+	 * etc. but for now we'll play it safe
+	 * XXX we will probably deadlock if we take an interrupt while sc_lock
+	 * is held and then try to printf()
+	 */
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+
+	/* init engine here */	
 	gffb_init(sc);
-	printf("put: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT));
-	printf("get: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET));
+
+	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
+	    &gffb_accessops);
+	sc->vd.init_screen = gffb_init_screen;
+
 
 	ri = &sc->sc_console_screen.scr_ri;
 
-#if notyet
 	sc->sc_gc.gc_bitblt = gffb_bitblt;
 	sc->sc_gc.gc_blitcookie = sc;
-	sc->sc_gc.gc_rop = R128_ROP3_S;
-#endif
+	sc->sc_gc.gc_rop = 0xcc;
 
 	if (is_console) {
 		vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
 		    &defattr);
 		sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
 
-#if notyet
 		gffb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
-		    ri->ri_devcmap[(defattr >> 16) & 0xff]);
-#else
-		memset(sc->sc_fbaddr + 0x2000,
-		    ri->ri_devcmap[(defattr >> 16) & 0xff],
-		    sc->sc_height * sc->sc_stride);
-#endif
+		    ri->ri_devcmap[(defattr >> 16) & 0xf]);
+		
 		sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
 		sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
 		sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
 		sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
-#if notyet
+		
 		glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
 				(0x800000 / sc->sc_stride) - sc->sc_height - 5,
 				sc->sc_width,
 				ri->ri_font->fontwidth,
 				ri->ri_font->fontheight,
 				defattr);
-#endif
+		
 		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
 		    defattr);
 		vcons_replay_msgbuf(&sc->sc_console_screen);
@@ -305,14 +311,13 @@ gffb_attach(device_t parent, device_t se
 			    &defattr);
 		} else
 			(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
-#if notyet
+		
 		glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
 				(0x800000 / sc->sc_stride) - sc->sc_height - 5,
 				sc->sc_width,
 				ri->ri_font->fontwidth,
 				ri->ri_font->fontheight,
 				defattr);
-#endif
 	}
 
 	j = 0;
@@ -334,6 +339,30 @@ gffb_attach(device_t parent, device_t se
 	aa.accesscookie = &sc->vd;
 
 	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
+
+#ifdef GFFB_DEBUG
+	for (i = 0; i < 40; i++) {
+		for (j = 0; j < 40; j++) {
+			gffb_rectfill(sc, i * 20, j * 20, 20, 20,
+			    (i + j ) & 1 ? 0xe0e0e0e0 : 0x03030303);
+		}
+	}
+	
+	//gffb_bitblt(sc, 0, 800, 10, 10, 400, 300, 0xcc);
+	gffb_rectfill(sc, 0, 800, 1280, 224, 0x92929292);
+	gffb_bitblt(sc, 0, 10, 10, 810, 200, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 10, 840, 300, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 10, 870, 400, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 10, 900, 500, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 10, 930, 600, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 610, 810, 200, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 610, 840, 300, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 610, 870, 400, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 610, 900, 500, 20, 0xcc);
+	gffb_bitblt(sc, 0, 10, 610, 930, 600, 20, 0xcc);
+	gffb_sync(sc);
+	printf("put %x current %x\n", sc->sc_put, sc->sc_current);
+#endif
 }
 
 static int
@@ -389,12 +418,10 @@ gffb_ioctl(void *v, void *vs, u_long cmd
 			if(new_mode == WSDISPLAYIO_MODE_EMUL) {
 				gffb_init(sc);
 				gffb_restore_palette(sc);
-#if notyet
 				glyphcache_wipe(&sc->sc_gc);
 				gffb_rectfill(sc, 0, 0, sc->sc_width,
 				    sc->sc_height, ms->scr_ri.ri_devcmap[
-				    (ms->scr_defattr >> 16) & 0xff]);
-#endif
+				    (ms->scr_defattr >> 16) & 0xf]);
 				vcons_redraw_screen(ms);
 			}
 		}
@@ -486,23 +513,22 @@ gffb_init_screen(void *cookie, struct vc
 
 	rasops_init(ri, 0, 0);
 	ri->ri_caps = WSSCREEN_WSCOLORS;
+#if 0
 	scr->scr_flags |= VCONS_DONT_READ;
+#endif
 
 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
 		    sc->sc_width / ri->ri_font->fontwidth);
 
 	ri->ri_hw = scr;
-#if notyet
+
+	sc->sc_putchar = ri->ri_ops.putchar;
 	ri->ri_ops.copyrows = gffb_copyrows;
 	ri->ri_ops.copycols = gffb_copycols;
 	ri->ri_ops.eraserows = gffb_eraserows;
 	ri->ri_ops.erasecols = gffb_erasecols;
 	ri->ri_ops.cursor = gffb_cursor;
-	if (FONT_IS_ALPHA(ri->ri_font)) {
-		ri->ri_ops.putchar = gffb_putchar_aa;
-	} else
-		ri->ri_ops.putchar = gffb_putchar;
-#endif
+	ri->ri_ops.putchar = gffb_putchar;
 }
 
 static int
@@ -514,7 +540,7 @@ gffb_putcmap(struct gffb_softc *sc, stru
 	int i, error;
 	u_char rbuf[256], gbuf[256], bbuf[256];
 
-#ifdef R128FB_DEBUG
+#ifdef GFFB_DEBUG
 	aprint_debug("putcmap: %d %d\n",index, count);
 #endif
 	if (cm->index >= 256 || cm->count > 256 ||
@@ -619,6 +645,7 @@ gffb_dma_kickoff(struct gffb_softc *sc)
 		scratch = *sc->sc_fbaddr;
 		bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT,
 		    sc->sc_put);
+		membar_sync();
 	}
 }
 
@@ -662,26 +689,26 @@ gffb_make_room(struct gffb_softc *sc, in
 			sc->sc_free = 0x2000 - sc->sc_current;
 			if (sc->sc_free < size) {
 				gffb_dmanext(sc, 0x20000000);
-				if(get <= SKIPS) {
-					if (sc->sc_put <= SKIPS) {
+				if(get <= (SKIPS << 2)) {
+					if (sc->sc_put <= (SKIPS << 2)) {
 						/* corner case - will be idle */
 						bus_space_write_4(sc->sc_memt,
 						    sc->sc_regh, GFFB_FIFO_PUT,
-						    SKIPS + 1);
+						    (SKIPS + 1) << 2);
 					}
 					do {
 						get = bus_space_read_4(
 						    sc->sc_memt, sc->sc_regh,
 						    GFFB_FIFO_GET);
-					} while (get <= SKIPS);
+					} while (get <= (SKIPS << 2));
 				}
 				bus_space_write_4(sc->sc_memt, sc->sc_regh,
-				     GFFB_FIFO_PUT, SKIPS);
-				sc->sc_current = sc->sc_put = SKIPS;
-				sc->sc_free = get - (SKIPS + 1);
+				     GFFB_FIFO_PUT, SKIPS << 2);
+				sc->sc_current = sc->sc_put = (SKIPS << 2);
+				sc->sc_free = get - ((SKIPS + 1) << 2);
 			}
 		} else
-			sc->sc_free = get - sc->sc_current - 1;
+			sc->sc_free = get - sc->sc_current - 4;
 	}
 }
 
@@ -689,28 +716,41 @@ static void
 gffb_sync(struct gffb_softc *sc)
 {
 	int bail;
+	int i;
 
-	bail = 100000;
+	gffb_dma_kickoff(sc);	/* just in case */
+
+	bail = 100000000;
 	while ((bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET) !=
 	    sc->sc_put) && (bail > 0)) {
+#if 0
 		bail--;
-		delay(1);
+#endif
 	}
-	if (bail == 0) printf("DMA timed out\n");
+	if (bail == 0) goto crap;
 
-	bail = 100000;
+	bail = 100000000;
 	while((bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_BUSY) != 0) &&
 	    (bail > 0)) {
+#if 0
 		bail--;
-		delay(1);
+#endif
 	}
-	if (bail == 0) printf("engine timed out\n");
+	if (bail == 0) goto crap;
+	return;
+crap:
+	sc->sc_put = 0;
+	sc->sc_current = 0;
+	for (i = 0; i < 0x2000; i += 4)
+		bus_space_write_stream_4(sc->sc_memt, sc->sc_fbh, i, 0);
+//	printf("DMA lockup\n");	
 }
 
 static void
 gffb_init(struct gffb_softc *sc)
 {
 	int i;
+	uint32_t foo;
 
 	/* init display start */
 	bus_space_write_4(sc->sc_memt, sc->sc_regh,
@@ -736,6 +776,14 @@ gffb_init(struct gffb_softc *sc)
 		bus_space_write_4(sc->sc_memt, sc->sc_regh,
 		    GFFB_PMC + 0x244 + (i * 0x10), sc->sc_vramsize - 1);
 	}
+
+	for (i = 0; i < 8; i++) {
+		bus_space_write_4(sc->sc_memt, sc->sc_regh,
+		    GFFB_PFB + 0x0240 + (i * 0x10), 0);
+		bus_space_write_4(sc->sc_memt, sc->sc_regh,
+		    GFFB_PFB + 0x0244 + (i * 0x10), sc->sc_vramsize - 1);
+	}
+
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN, 0x80000010);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x04, 0x80011201);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x08, 0x80000011);
@@ -793,7 +841,19 @@ gffb_init(struct gffb_softc *sc)
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2094, 0x00007fff);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2098, 0x00000002);	/* start of command buffer? */
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x209c, 0x00000002);
-	/* __BIG_ENDIAN part? */
+#if BYTE_ORDER == BIG_ENDIAN
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2010, 0x01088042);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2020, 0x01088043);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2030, 0x01088044);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2040, 0x01088019);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2050, 0x0108a05c);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2060, 0x0108809f);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2070, 0x0108804a);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2080, 0x01098077);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2034, 0x00000001);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2074, 0x00000001);
+#endif
+
 	/* PGRAPH setup */
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PFIFO + 0x0500, 0);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PFIFO + 0x0504, 0x00000001);
@@ -826,6 +886,46 @@ gffb_init(struct gffb_softc *sc)
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PFIFO + 0x1254, 0x00000001);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PFIFO + 0x0500, 0x00000001);
 
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0080, 0xFFFFFFFF);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0080, 0x00000000);
+
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0140, 0x00000000);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0100, 0xFFFFFFFF);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0144, 0x10010100);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0714, 0xFFFFFFFF);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0720, 0x00000001);
+	foo = bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0710);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0710,
+	    foo & 0x0007ff00);
+	foo = bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0710);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0710,
+	    foo | 0x00020100);
+
+	/* NV_ARCH_10 */
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0084, 0x00118700);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0088, 0x24E00810);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x008C, 0x55DE0030);
+
+	for(i = 0; i < 128; i += 4) {
+		bus_space_write_4(sc->sc_memt, sc->sc_regh,
+		    GFFB_PGRAPH + 0x0B00 + i,
+		    bus_space_read_4(sc->sc_memt, sc->sc_regh,
+		      GFFB_PFB + 0x0240 + i));
+	}
+
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x640, 0);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x644, 0);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x684, sc->sc_vramsize - 1);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x688, sc->sc_vramsize - 1);
+
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0810, 0x00000000);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0608, 0xFFFFFFFF);
+
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x053C, 0);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0540, 0);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0544, 0x00007FFF);
+	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PGRAPH + 0x0548, 0x00007FFF);
+
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_CMDSTART, 0x00000002);
 	bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET, 0);
 	sc->sc_put = 0;
@@ -856,17 +956,222 @@ gffb_init(struct gffb_softc *sc)
 	gffb_dmastart(sc, SURFACE_FORMAT, 4);
 	gffb_dmanext(sc, SURFACE_FORMAT_DEPTH8);
 	gffb_dmanext(sc, sc->sc_stride | (sc->sc_stride << 16));
-	gffb_dmanext(sc, 0);
-	gffb_dmanext(sc, 0);
+	gffb_dmanext(sc, 0x2000);	/* src offset */
+	gffb_dmanext(sc, 0x2000);	/* dst offset */
 
 	gffb_dmastart(sc, RECT_FORMAT, 1);
 	gffb_dmanext(sc, RECT_FORMAT_DEPTH8);
 
+	gffb_dmastart(sc, PATTERN_FORMAT, 1);
+	gffb_dmanext(sc, PATTERN_FORMAT_DEPTH8);
+
+	gffb_dmastart(sc, PATTERN_COLOR_0, 4);
+	gffb_dmanext(sc, 0xffffffff);
+	gffb_dmanext(sc, 0xffffffff);
+	gffb_dmanext(sc, 0xffffffff);
+	gffb_dmanext(sc, 0xffffffff);
+	
 	gffb_dmastart(sc, ROP_SET, 1);
 	gffb_dmanext(sc, 0xcc);
+	sc->sc_rop = 0xcc;
 
 	gffb_dma_kickoff(sc);
 	gffb_sync(sc);
 	printf("put %x current %x\n", sc->sc_put, sc->sc_current);
+	
 }
 
+static void
+gffb_rop(struct gffb_softc *sc, int rop)
+{
+	if (rop == sc->sc_rop)
+		return;
+	sc->sc_rop = rop;
+	gffb_dmastart(sc, ROP_SET, 1);
+	gffb_dmanext(sc, rop);
+}	
+
+static void
+gffb_rectfill(struct gffb_softc *sc, int x, int y, int wi, int he,
+     uint32_t colour)
+{
+	mutex_enter(&sc->sc_lock);
+	gffb_rop(sc, 0xcc);
+
+	gffb_dmastart(sc, RECT_SOLID_COLOR, 1);
+	gffb_dmanext(sc, colour);
+
+	gffb_dmastart(sc, RECT_SOLID_RECTS(0), 2);
+	gffb_dmanext(sc, (x << 16) | y);
+	gffb_dmanext(sc, (wi << 16) | he);
+	gffb_dma_kickoff(sc);
+	mutex_exit(&sc->sc_lock);
+}
+
+static void
+gffb_bitblt(void *cookie, int xs, int ys, int xd, int yd,
+    int wi, int he, int rop)
+{
+	struct gffb_softc *sc = cookie;
+
+	mutex_enter(&sc->sc_lock);
+
+	gffb_rop(sc, rop);
+
+	gffb_dmastart(sc, BLIT_POINT_SRC, 3);
+	gffb_dmanext(sc, (ys << 16) | xs);
+	gffb_dmanext(sc, (yd << 16) | xd);
+	gffb_dmanext(sc, (he << 16) | wi);
+	gffb_dma_kickoff(sc);
+	mutex_exit(&sc->sc_lock);
+}
+
+static void
+gffb_cursor(void *cookie, int on, int row, int col)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int x, y, wi, he;
+	
+	wi = ri->ri_font->fontwidth;
+	he = ri->ri_font->fontheight;
+	
+	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
+		x = ri->ri_ccol * wi + ri->ri_xorigin;
+		y = ri->ri_crow * he + ri->ri_yorigin;
+		if (ri->ri_flg & RI_CURSOR) {
+			gffb_bitblt(sc, x, y, x, y, wi, he, 0x33);
+			ri->ri_flg &= ~RI_CURSOR;
+		}
+		ri->ri_crow = row;
+		ri->ri_ccol = col;
+		if (on) {
+			x = ri->ri_ccol * wi + ri->ri_xorigin;
+			y = ri->ri_crow * he + ri->ri_yorigin;
+			gffb_bitblt(sc, x, y, x, y, wi, he, 0x33);
+			ri->ri_flg |= RI_CURSOR;
+		}
+	} else {
+		scr->scr_ri.ri_crow = row;
+		scr->scr_ri.ri_ccol = col;
+		scr->scr_ri.ri_flg &= ~RI_CURSOR;
+	}
+
+}
+
+static void
+gffb_putchar(void *cookie, int row, int col, u_int c, long attr)
+{
+	struct rasops_info *ri = cookie;
+	struct wsdisplay_font *font = PICK_FONT(ri, c);
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int x, y, wi, he, rv = GC_NOPE;
+	uint32_t bg;
+
+	if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 
+		return;
+
+	if (!CHAR_IN_FONT(c, font))
+		return;
+
+	wi = font->fontwidth;
+	he = font->fontheight;
+	
+	x = ri->ri_xorigin + col * wi;
+	y = ri->ri_yorigin + row * he;
+	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
+	
+	if (c == 0x20) {
+		gffb_rectfill(sc, x, y, wi, he, bg);
+		return;
+	}
+	rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
+	if (rv == GC_OK)
+		return;
+
+	mutex_enter(&sc->sc_lock);
+	gffb_sync(sc);
+	sc->sc_putchar(cookie, row, col, c, attr);
+	membar_sync();
+	mutex_exit(&sc->sc_lock);
+
+	if (rv == GC_ADD) {
+		glyphcache_add(&sc->sc_gc, c, x, y);
+	}
+}
+
+static void
+gffb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int32_t xs, xd, y, width, height;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
+		xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_font->fontwidth * ncols;
+		height = ri->ri_font->fontheight;
+		gffb_bitblt(sc, xs, y, xd, y, width, height, 0xcc);
+	}
+}
+
+static void
+gffb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int32_t x, y, width, height, fg, bg, ul;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_font->fontwidth * ncols;
+		height = ri->ri_font->fontheight;
+		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
+
+		gffb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
+	}
+}
+
+static void
+gffb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int32_t x, ys, yd, width, height;
+
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		x = ri->ri_xorigin;
+		ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
+		yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
+		width = ri->ri_emuwidth;
+		height = ri->ri_font->fontheight * nrows;
+		gffb_bitblt(sc, x, ys, x, yd, width, height, 0xcc);
+	}
+}
+
+static void
+gffb_eraserows(void *cookie, int row, int nrows, long fillattr)
+{
+	struct rasops_info *ri = cookie;
+	struct vcons_screen *scr = ri->ri_hw;
+	struct gffb_softc *sc = scr->scr_cookie;
+	int32_t x, y, width, height, fg, bg, ul;
+	
+	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
+		x = ri->ri_xorigin;
+		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
+		width = ri->ri_emuwidth;
+		height = ri->ri_font->fontheight * nrows;
+		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
+
+		gffb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
+	}
+}

Reply via email to