Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci add acceleration support, for Sun XVR-1200 and c...



details:   https://anonhg.NetBSD.org/src/rev/78167da8a71b
branches:  trunk
changeset: 781954:78167da8a71b
user:      macallan <macallan%NetBSD.org@localhost>
date:      Tue Oct 09 21:59:19 2012 +0000

description:
add acceleration support, for Sun XVR-1200 and compatible only so far
adapted from OpenBSD with various improvements, no support for Expert3D has
been added
this is still suboptimal since we have to sync the engine all the time but
it's an improvement over software-only operation

diffstat:

 sys/dev/pci/wcfb.c    |  364 ++++++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/pci/wcfbreg.h |   35 ++++-
 2 files changed, 370 insertions(+), 29 deletions(-)

diffs (truncated from 510 to 300 lines):

diff -r 3662c74127e2 -r 78167da8a71b sys/dev/pci/wcfb.c
--- a/sys/dev/pci/wcfb.c        Tue Oct 09 21:32:54 2012 +0000
+++ b/sys/dev/pci/wcfb.c        Tue Oct 09 21:59:19 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wcfb.c,v 1.11 2012/03/13 18:40:34 elad Exp $ */
+/*     $NetBSD: wcfb.c,v 1.12 2012/10/09 21:59:19 macallan Exp $ */
 
 /*-
  * Copyright (c) 2010 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wcfb.c,v 1.11 2012/03/13 18:40:34 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wcfb.c,v 1.12 2012/10/09 21:59:19 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -104,7 +104,7 @@
        void (*eraserows)(void *, int, int, long);
        void (*putchar)(void *, int, int, u_int, long);
        void (*cursor)(void *, int, int, int);
-       
+       int sc_is_jfb;
 };
 
 static void    wcfb_init_screen(void *, struct vcons_screen *, int, long *);
@@ -130,8 +130,24 @@
 static void    wcfb_copyrows(void *, int, int, int);
 static void    wcfb_eraserows(void *, int, int, long);
 
+static void    wcfb_acc_putchar(void *, int, int, u_int, long);
+static void    wcfb_acc_cursor(void *, int, int, int);
+static void    wcfb_acc_copycols(void *, int, int, int, int);
+static void    wcfb_acc_erasecols(void *, int, int, int, long);
+static void    wcfb_acc_copyrows(void *, int, int, int);
+static void    wcfb_acc_eraserows(void *, int, int, long);
+
 static void    wcfb_putpalreg(struct wcfb_softc *, int, int, int, int);
 
+static void    wcfb_bitblt(struct wcfb_softc *, int, int, int, int, int,
+                       int, uint32_t);
+static void    wcfb_rectfill(struct wcfb_softc *, int, int, int, int, int);
+static void    wcfb_rop_common(struct wcfb_softc *, bus_addr_t, int, int, int, 
+                       int, int, int, uint32_t, int32_t);
+static void    wcfb_rop_jfb(struct wcfb_softc *, int, int, int, int, int, int, 
+                       uint32_t, int32_t);
+static int     wcfb_rop_wait(struct wcfb_softc *);
+
 static int
 wcfb_match(device_t parent, cfdata_t match, void *aux)
 {
@@ -156,7 +172,8 @@
        uint32_t                reg;
        unsigned long           defattr;
        bool                    is_console = 0;
-       void *wtf;
+       void                    *wtf;
+       uint32_t                sub;
 
        sc->sc_dev = self;
        sc->putchar = NULL;
@@ -195,14 +212,29 @@
        sc->sc_fbaddr = bus_space_vaddr(sc->sc_memt, sc->sc_fbh);
 
        sc->sc_fb0off =
-           bus_space_read_4(sc->sc_regt, sc->sc_regh, WC_FB8_ADDR0) - sc->sc_fb;
+           bus_space_read_4(sc->sc_regt, sc->sc_regh,
+               WC_FB8_ADDR0) - sc->sc_fb;
        sc->sc_fb0 = sc->sc_fbaddr + sc->sc_fb0off;
        sc->sc_fb1off = 
-           bus_space_read_4(sc->sc_regt, sc->sc_regh, WC_FB8_ADDR1) - sc->sc_fb;
+           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;
 
+       sub = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_SUBSYS_ID_REG);
+       printf("subsys: %08x\n", sub);
+       switch (sub) {
+               case WC_XVR1200:
+                       sc->sc_is_jfb = 1;
+                       break;
+               default:
+                       sc->sc_is_jfb = 0;
+       }
+
        reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, WC_RESOLUTION);
        sc->sc_height = (reg >> 16) + 1;
+#ifdef WCFB_DEBUG
+       sc->sc_height -= 200;
+#endif
        sc->sc_width = (reg & 0xffff) + 1;
        sc->sc_stride = 1 <<
            ((bus_space_read_4(sc->sc_regt, sc->sc_regh, WC_CONFIG) &
@@ -210,11 +242,14 @@
        printf("%s: %d x %d, %d\n", device_xname(sc->sc_dev), 
            sc->sc_width, sc->sc_height, sc->sc_stride);
 
-       sc->sc_shadow = kmem_alloc(sc->sc_stride * sc->sc_height, KM_SLEEP);
-       if (sc->sc_shadow == NULL) {
-               printf("%s: failed to allocate shadow buffer\n",
-                   device_xname(self));
-               return;
+       if (sc->sc_is_jfb == 0) {
+               sc->sc_shadow = kmem_alloc(sc->sc_stride * sc->sc_height,
+                   KM_SLEEP);
+               if (sc->sc_shadow == NULL) {
+                       printf("%s: failed to allocate shadow buffer\n",
+                           device_xname(self));
+                       return;
+               }
        }
 
        for (i = 0x40; i < 0x100; i += 16) {
@@ -269,10 +304,17 @@
                    &defattr);
                sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
 
-               memset(sc->sc_fb0, ri->ri_devcmap[(defattr >> 16) & 0xff],
-                   sc->sc_stride * sc->sc_height);
-               memset(sc->sc_fb1, ri->ri_devcmap[(defattr >> 16) & 0xff],
-                   sc->sc_stride * sc->sc_height);
+               if (sc->sc_is_jfb) {
+                       wcfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
+                               ri->ri_devcmap[(defattr >> 16) & 0xff]);
+               } else {
+                       memset(sc->sc_fb0,
+                           ri->ri_devcmap[(defattr >> 16) & 0xff],
+                           sc->sc_stride * sc->sc_height);
+                       memset(sc->sc_fb1,
+                           ri->ri_devcmap[(defattr >> 16) & 0xff],
+                           sc->sc_stride * sc->sc_height);
+               }
                sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
                sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
                sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
@@ -340,7 +382,8 @@
         * restrict all other mappings to processes with superuser privileges
         * or the kernel itself
         */
-       if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM,
+       if (kauth_authorize_machdep(kauth_cred_get(), 
+           KAUTH_MACHDEP_UNMANAGEDMEM,
            NULL, NULL, NULL, NULL) != 0) {
                aprint_normal_dev(sc->sc_dev, "mmap() rejected.\n");
                return -1;
@@ -370,8 +413,11 @@
        ri->ri_stride = sc->sc_stride;
        ri->ri_flg = RI_CENTER /*| RI_FULLCLEAR*/;
 
-       ri->ri_bits = sc->sc_shadow;
-
+       if (sc->sc_is_jfb) {
+               ri->ri_bits = sc->sc_fb0;
+       } else {
+               ri->ri_bits = sc->sc_shadow;
+       }
        if (existing) {
                ri->ri_flg |= RI_CLEAR;
        }
@@ -389,12 +435,21 @@
        sc->copycols = ri->ri_ops.copycols;
        sc->erasecols = ri->ri_ops.erasecols;
 
-       ri->ri_ops.copyrows = wcfb_copyrows;
-       ri->ri_ops.copycols = wcfb_copycols;
-       ri->ri_ops.eraserows = wcfb_eraserows;
-       ri->ri_ops.erasecols = wcfb_erasecols;
-       ri->ri_ops.putchar = wcfb_putchar;
-       ri->ri_ops.cursor = wcfb_cursor;
+       if (sc->sc_is_jfb) {
+               ri->ri_ops.copyrows = wcfb_acc_copyrows;
+               ri->ri_ops.copycols = wcfb_acc_copycols;
+               ri->ri_ops.eraserows = wcfb_acc_eraserows;
+               ri->ri_ops.erasecols = wcfb_acc_erasecols;
+               ri->ri_ops.putchar = wcfb_acc_putchar;
+               ri->ri_ops.cursor = wcfb_acc_cursor;
+       } else {
+               ri->ri_ops.copyrows = wcfb_copyrows;
+               ri->ri_ops.copycols = wcfb_copycols;
+               ri->ri_ops.eraserows = wcfb_eraserows;
+               ri->ri_ops.erasecols = wcfb_erasecols;
+               ri->ri_ops.putchar = wcfb_putchar;
+               ri->ri_ops.cursor = wcfb_cursor;
+       }
 }
 
 static void
@@ -572,3 +627,264 @@
                to1 += sc->sc_stride;
        }
 }
+
+static void
+wcfb_bitblt(struct wcfb_softc *sc, int sx, int sy, int dx, int dy, int w,
+                int h, uint32_t rop)
+{
+       wcfb_rop_wait(sc);
+       wcfb_rop_jfb(sc, sx, sy, dx, dy, w, h, rop, 0xff);
+}
+
+static void
+wcfb_rectfill(struct wcfb_softc *sc, int x, int y, int w, int h, int bg)
+{
+       int32_t mask;
+
+       /* pixels to set... */
+       mask = 0xff & 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
+wcfb_rop_common(struct wcfb_softc *sc, bus_addr_t reg, int sx, int sy,
+    int dx, int dy, int w, int h, uint32_t rop, int32_t planemask)
+{
+       int dir = 0;
+
+       /*
+        * Compute rop direction. This only really matters for
+        * screen-to-screen copies.
+        */
+       if (sy < dy /* && sy + h > dy */) {
+               sy += h - 1;
+               dy += h;
+               dir |= WC_BLT_DIR_BACKWARDS_Y;
+       }
+       if (sx < dx /* && sx + w > dx */) {
+               sx += w - 1;
+               dx += w;
+               dir |= WC_BLT_DIR_BACKWARDS_X;
+       }
+
+       /* Which one of those below is your magic number for today? */
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x61000001);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x6301c080);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x80000000);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, rop);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, planemask);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x64000303);
+       /*
+        * This value is a pixel offset within the destination area. It is
+        * probably used to define complex polygon shapes, with the
+        * last pixel in the list being back to (0,0).
+        */
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, WCFB_COORDS(0, 0));
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x00030000);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x2200010d);
+
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x33f01000 | dir);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, WCFB_COORDS(dx, dy));
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, WCFB_COORDS(w, h));
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, WCFB_COORDS(sx, sy));
+}
+
+
+static void
+wcfb_rop_jfb(struct wcfb_softc *sc, int sx, int sy, int dx, int dy,
+             int w, int h, uint32_t rop, int32_t planemask)
+{
+       bus_addr_t reg = WC_JFB_ENGINE;
+       uint32_t spr, splr;
+
+#if 0
+       /*
+        * Pick the current spr and splr values from the communication
+        * area if possible.
+        */
+       if (sc->sc_comm != NULL) {
+               spr = sc->sc_comm[IFB_SHARED_TERM8_SPR >> 2];
+               splr = sc->sc_comm[IFB_SHARED_TERM8_SPLR >> 2];
+       } else 
+#endif
+       {
+               /* supposedly sane defaults */
+               spr = 0x54ff0303;
+               splr = 0x5c0000ff;
+       }
+
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x00400016);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x5b000002);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x5a000000);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, spr);
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, splr);
+
+       wcfb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
+
+       bus_space_write_4(sc->sc_regt, sc->sc_regh, reg, 0x5a000001);



Home | Main Index | Thread Index | Old Index