Module Name:    src
Committed By:   macallan
Date:           Fri Mar 24 00:51:43 UTC 2017

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

Log Message:
- clean up some testing & debugging goop
- 0xff is transparent, so restrict ourself to just 4 bit colour, all we need
  for wscons
- support WSDISPLAYIO_GET_FBINFO etc. for wsfb, allow mmap()ing the fb etc.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/pci/wcfb.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/wcfb.c
diff -u src/sys/dev/pci/wcfb.c:1.14 src/sys/dev/pci/wcfb.c:1.15
--- src/sys/dev/pci/wcfb.c:1.14	Thu Jul 14 10:19:06 2016
+++ src/sys/dev/pci/wcfb.c	Fri Mar 24 00:51:43 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: wcfb.c,v 1.14 2016/07/14 10:19:06 msaitoh Exp $ */
+/*	$NetBSD: wcfb.c,v 1.15 2017/03/24 00:51:43 macallan Exp $ */
 
 /*
  * Copyright (c) 2007, 2008, 2009 Miodrag Vallat.
@@ -20,7 +20,7 @@
 /* a driver for (some) 3DLabs Wildcat cards, based on OpenBSD's ifb driver */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wcfb.c,v 1.14 2016/07/14 10:19:06 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wcfb.c,v 1.15 2017/03/24 00:51:43 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,10 +72,10 @@ struct wcfb_softc {
 	bus_space_tag_t sc_regt, sc_wtft;
 	bus_space_tag_t sc_iot;
 
-	bus_space_handle_t sc_fbh, sc_wtfh;
+	bus_space_handle_t sc_fbh;
 	bus_space_handle_t sc_regh;
-	bus_addr_t sc_fb, sc_reg, sc_wtf;
-	bus_size_t sc_fbsize, sc_regsize, sc_wtfsize;
+	bus_addr_t sc_fb, sc_reg;
+	bus_size_t sc_fbsize, sc_regsize;
 
 	int sc_width, sc_height, sc_stride;
 	int sc_locked;
@@ -89,7 +89,7 @@ struct wcfb_softc {
 	u_char sc_cmap_red[256];
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];
-	uint32_t sc_fb0off, sc_fb1off;
+	uint32_t sc_fb0off, sc_fb1off, sc_fb8size;
 
 	void (*copycols)(void *, int, int, int, int);
 	void (*erasecols)(void *, int, int, int, long);
@@ -165,7 +165,6 @@ wcfb_attach(device_t parent, device_t se
 	uint32_t		reg;
 	unsigned long		defattr;
 	bool			is_console = 0;
-	void 			*wtf;
 	uint32_t		sub;
 
 	sc->sc_dev = self;
@@ -188,22 +187,17 @@ wcfb_attach(device_t parent, device_t se
 		    device_xname(sc->sc_dev));
 	}
 
-	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR,
+	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM,
+	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
 	    &sc->sc_memt, &sc->sc_fbh, &sc->sc_fb, &sc->sc_fbsize)) {
 		aprint_error("%s: failed to map framebuffer.\n",
 		    device_xname(sc->sc_dev));
 	}
 
-	if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR,
-	    &sc->sc_wtft, &sc->sc_wtfh, &sc->sc_wtf, &sc->sc_wtfsize)) {
-		aprint_error("%s: failed to map wtf.\n",
-		    device_xname(sc->sc_dev));
-	}
-	wtf = bus_space_vaddr(sc->sc_wtft, sc->sc_wtfh);
-	memset(wtf, 0, 0x100000);
-
 	sc->sc_fbaddr = bus_space_vaddr(sc->sc_memt, sc->sc_fbh);
-
+#ifdef DEBUG
+	memset(sc->sc_fbaddr, 0, sc->sc_fbsize);
+#endif
 	sc->sc_fb0off =
 	    bus_space_read_4(sc->sc_regt, sc->sc_regh,
 	        WC_FB8_ADDR0) - sc->sc_fb;
@@ -212,6 +206,8 @@ wcfb_attach(device_t parent, device_t se
 	    bus_space_read_4(sc->sc_regt, sc->sc_regh,
 	        WC_FB8_ADDR1) - sc->sc_fb;
 	sc->sc_fb1 = sc->sc_fbaddr + sc->sc_fb1off;
+	sc->sc_fb8size = 2 * (sc->sc_fb1off - sc->sc_fb0off);
+printf("fb %08x %08x %08x\n", sc->sc_fb0off, sc->sc_fb1off, sc->sc_fb8size);
 
 	sub = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_SUBSYS_ID_REG);
 	aprint_normal("subsys: %08x\n", sub);
@@ -257,6 +253,18 @@ wcfb_attach(device_t parent, device_t se
 	/* make sure video output is on */
 	bus_space_write_4(sc->sc_regt, sc->sc_regh, WC_DPMS_STATE, WC_DPMS_ON);
 
+#if 0
+	/* testing & debugging voodoo */
+	memset(sc->sc_fb0, 0x01, 0x00100000);
+	memset(sc->sc_fb1, 0x00, 0x00100000);
+	wcfb_rop_wait(sc);
+	wcfb_rop_jfb(sc, 0, 0, 0, 0, 600, 600, WC_ROP_SET, 0xffffffff);
+	wcfb_rop_wait(sc);
+	delay(4000000);
+	bus_space_write_4(sc->sc_regt, sc->sc_regh, WC_FB8_ADDR1,
+	    bus_space_read_4(sc->sc_regt, sc->sc_regh, WC_FB8_ADDR0));
+	delay(8000000);
+#endif
 	sc->sc_defaultscreen_descr = (struct wsscreen_descr){
 		"default",
 		0, 0,
@@ -336,10 +344,72 @@ wcfb_attach(device_t parent, device_t se
 }
 
 static int
+wcfb_putcmap(struct wcfb_softc *sc, struct wsdisplay_cmap *cm)
+{
+	u_char *r, *g, *b;
+	u_int index = cm->index;
+	u_int count = cm->count;
+	int i, error;
+	u_char rbuf[256], gbuf[256], bbuf[256];
+
+	if (cm->index >= 256 || cm->count > 256 ||
+	    (cm->index + cm->count) > 256)
+		return EINVAL;
+	error = copyin(cm->red, &rbuf[index], count);
+	if (error)
+		return error;
+	error = copyin(cm->green, &gbuf[index], count);
+	if (error)
+		return error;
+	error = copyin(cm->blue, &bbuf[index], count);
+	if (error)
+		return error;
+
+	memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
+	memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
+	memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
+
+	r = &sc->sc_cmap_red[index];
+	g = &sc->sc_cmap_green[index];
+	b = &sc->sc_cmap_blue[index];
+
+	for (i = 0; i < count; i++) {
+		wcfb_putpalreg(sc, index, *r, *g, *b);
+		index++;
+		r++, g++, b++;
+	}
+	return 0;
+}
+
+static int
+wcfb_getcmap(struct wcfb_softc *sc, struct wsdisplay_cmap *cm)
+{
+	u_int index = cm->index;
+	u_int count = cm->count;
+	int error;
+
+	if (index >= 255 || count > 256 || index + count > 256)
+		return EINVAL;
+
+	error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
+	if (error)
+		return error;
+	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
+	if (error)
+		return error;
+	error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int
 wcfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
     struct lwp *l)
 {
-	struct wcfb_softc *sc = v;
+	struct vcons_data *vd = v;
+	struct wcfb_softc *sc = vd->cookie;
 
 	switch (cmd) {
 	case WSDISPLAYIO_GTYPE:
@@ -360,17 +430,45 @@ wcfb_ioctl(void *v, void *vs, u_long cmd
 		/*int new_mode = *(int*)data, i;*/
 		}
 		return 0;
-	}
 
+	case WSDISPLAYIO_GETCMAP:
+		return wcfb_getcmap(sc,
+		    (struct wsdisplay_cmap *)data);
+
+	case WSDISPLAYIO_PUTCMAP:
+		return wcfb_putcmap(sc,
+		    (struct wsdisplay_cmap *)data);
+
+	case WSDISPLAYIO_GET_FBINFO: {
+		struct wsdisplayio_fbinfo *fbi = data;
+
+		fbi->fbi_fbsize = sc->sc_fb8size;
+		fbi->fbi_fboffset = 0;
+		fbi->fbi_width = sc->sc_width;
+		fbi->fbi_height = sc->sc_height;
+		fbi->fbi_bitsperpixel = 8;
+		fbi->fbi_stride = sc->sc_stride;
+		fbi->fbi_pixeltype = WSFB_CI;
+		fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 256;
+		fbi->fbi_flags = WSFB_VRAM_IS_SPLIT;
+		return 0;
+		}
+	}
 	return EPASSTHROUGH;
 }
 
 static paddr_t
 wcfb_mmap(void *v, void *vs, off_t offset, int prot)
 {
-	struct wcfb_softc *sc = v;
+	struct vcons_data *vd = v;
+	struct wcfb_softc *sc = vd->cookie;
+
+	/* XXX in theory the order is not fixed... */
 
-	/* no point in allowing a wsfb map if we can't provide one */
+	if (offset < sc->sc_fb8size)
+		return bus_space_mmap(sc->sc_memt, sc->sc_fb + sc->sc_fb0off,
+		    offset, prot,
+		    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
 	/*
 	 * restrict all other mappings to processes with superuser privileges
 	 * or the kernel itself
@@ -382,13 +480,7 @@ wcfb_mmap(void *v, void *vs, off_t offse
 		return -1;
 	}
 
-#ifdef WSFB_FAKE_VGA_FB
-	if ((offset >= 0xa0000) && (offset < 0xbffff)) {
-
-		return bus_space_mmap(sc->sc_memt, sc->sc_gen.sc_fboffset,
-		   offset - 0xa0000, prot, BUS_SPACE_MAP_LINEAR);
-	}
-#endif
+	/* may want to mmap() registers at some point */
 
 	return -1;
 }
@@ -626,7 +718,7 @@ wcfb_bitblt(struct wcfb_softc *sc, int s
 		 int h, uint32_t rop)
 {
 	wcfb_rop_wait(sc);
-	wcfb_rop_jfb(sc, sx, sy, dx, dy, w, h, rop, 0xff);
+	wcfb_rop_jfb(sc, sx, sy, dx, dy, w, h, rop, 0x0f);
 }
 
 static void
@@ -634,19 +726,17 @@ wcfb_rectfill(struct wcfb_softc *sc, int
 {
 	int32_t mask;
 
+	/* clear everything just in case... */
+	wcfb_rop_wait(sc);
+	wcfb_rop_jfb(sc, x, y, x, y, w, h, WC_ROP_CLEAR, 0xffffffff);
+
 	/* pixels to set... */
-	mask = 0xff & bg;
+	mask = 0x0f & bg;
 	if (mask != 0) {
 		wcfb_rop_wait(sc);
 		wcfb_rop_jfb(sc, x, y, x, y, w, h, WC_ROP_SET, mask);
 	}
 
-	/* pixels to clear... */
-	mask = 0xff & ~bg;
-	if (mask != 0) {
-		wcfb_rop_wait(sc);
-		wcfb_rop_jfb(sc, x, y, x, y, w, h, WC_ROP_CLEAR, mask);
-	}
 }
 
 void

Reply via email to