Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/usermode/dev add mmap support



details:   https://anonhg.NetBSD.org/src/rev/7153f89abd44
branches:  trunk
changeset: 772355:7153f89abd44
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Dec 30 19:32:32 2011 +0000

description:
add mmap support

diffstat:

 sys/arch/usermode/dev/vncfb.c |  89 +++++++++++++++++++++++++++++++++++++++---
 1 files changed, 81 insertions(+), 8 deletions(-)

diffs (183 lines):

diff -r 3a2991d37474 -r 7153f89abd44 sys/arch/usermode/dev/vncfb.c
--- a/sys/arch/usermode/dev/vncfb.c     Fri Dec 30 19:30:59 2011 +0000
+++ b/sys/arch/usermode/dev/vncfb.c     Fri Dec 30 19:32:32 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vncfb.c,v 1.8 2011/12/30 14:22:41 jmcneill Exp $ */
+/* $NetBSD: vncfb.c,v 1.9 2011/12/30 19:32:32 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2011 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -35,7 +35,7 @@
 #include "opt_wsemul.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vncfb.c,v 1.8 2011/12/30 14:22:41 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vncfb.c,v 1.9 2011/12/30 19:32:32 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -43,6 +43,8 @@
 #include <sys/device.h>
 #include <sys/kmem.h>
 
+#include <uvm/uvm_extern.h>
+
 #include <dev/wscons/wsconsio.h>
 
 #include <dev/wscons/wsdisplayvar.h>
@@ -57,6 +59,8 @@
 #include <machine/mainbus.h>
 #include <machine/thunk.h>
 
+#define VNCFB_REFRESH_INTERVAL 33      /* fb refresh interval when mapped */
+
 struct vncfb_fbops {
        void    (*copycols)(void *, int, int, int, int);
        void    (*erasecols)(void *, int, int, int, long);
@@ -74,7 +78,10 @@
        unsigned int            sc_height;
        unsigned int            sc_depth;
        int                     sc_mode;
+       uint8_t *               sc_mem;
+       size_t                  sc_memsize;
        uint8_t *               sc_framebuf;
+       size_t                  sc_framebufsize;
        struct vcons_data       sc_vd;
        struct vncfb_fbops      sc_ops;
 
@@ -82,6 +89,9 @@
 
        void                    *sc_ih;
        void                    *sc_sih;
+
+       callout_t               sc_callout;
+       void                    *sc_refresh_sih;
 };
 
 static int     vncfb_match(device_t, cfdata_t, void *);
@@ -107,6 +117,8 @@
 static void    vncfb_fillrect(struct vncfb_softc *, int, int, int, int, uint32_t);
 static int     vncfb_intr(void *);
 static void    vncfb_softintr(void *);
+static void    vncfb_refresh(void *);
+static void    vncfb_softrefresh(void *);
 
 static int     vncfb_kbd_enable(void *, int);
 static void    vncfb_kbd_set_leds(void *, int);
@@ -187,13 +199,17 @@
                panic("couldn't open VNC socket");
 #endif
 
-       sc->sc_framebuf = kmem_zalloc(sc->sc_width * sc->sc_height *
-           (sc->sc_depth / 8), KM_SLEEP);
-       KASSERT(sc->sc_framebuf != NULL);
+       sc->sc_framebufsize = sc->sc_width * sc->sc_height * (sc->sc_depth / 8);
+       sc->sc_memsize = sc->sc_framebufsize + PAGE_SIZE;
+
+       sc->sc_mem = kmem_zalloc(sc->sc_memsize, KM_SLEEP);
+       sc->sc_framebuf = (void *)round_page((vaddr_t)sc->sc_mem);
 
        aprint_naive("\n");
        aprint_normal(": %ux%u %ubpp (port %u)\n",
            sc->sc_width, sc->sc_height, sc->sc_depth, taa->u.vnc.port);
+       aprint_normal_dev(self, "mem @ %p\n", sc->sc_mem);
+       aprint_normal_dev(self, "fb  @ %p\n", sc->sc_framebuf);
 
        sc->sc_rfb.width = sc->sc_width;
        sc->sc_rfb.height = sc->sc_height;
@@ -210,6 +226,12 @@
        sc->sc_sih = softint_establish(SOFTINT_SERIAL, vncfb_softintr, sc);
        sc->sc_ih = sigio_intr_establish(vncfb_intr, sc);
 
+       sc->sc_refresh_sih = softint_establish(SOFTINT_SERIAL,
+           vncfb_softrefresh, sc);
+
+       callout_init(&sc->sc_callout, 0);
+       callout_setfunc(&sc->sc_callout, vncfb_refresh, sc);
+
        vcons_init(&sc->sc_vd, sc, &vncfb_defaultscreen, &vncfb_accessops);
        sc->sc_vd.init_screen = vncfb_init_screen;
 
@@ -438,12 +460,19 @@
                wdf->depth = ms->scr_ri.ri_depth;
                wdf->cmsize = 256;
                return 0;
+       case WSDISPLAYIO_LINEBYTES:
+               *(u_int *)data = sc->sc_width * (sc->sc_depth / 8);
+               return 0;
        case WSDISPLAYIO_SMODE:
                new_mode = *(int *)data;
                if (sc->sc_mode != new_mode) {
                        sc->sc_mode = new_mode;
-                       if (new_mode == WSDISPLAYIO_MODE_EMUL)
+                       if (new_mode == WSDISPLAYIO_MODE_EMUL) {
+                               callout_halt(&sc->sc_callout, NULL);
                                vcons_redraw_screen(ms);
+                       } else {
+                               callout_schedule(&sc->sc_callout, 1);
+                       }
                }
                return 0;
        default:
@@ -454,8 +483,26 @@
 static paddr_t
 vncfb_mmap(void *v, void *vs, off_t offset, int prot)
 {
-       /* TODO */
-       return -1;
+       struct vcons_data *vd = v;
+       struct vncfb_softc *sc = vd->cookie;
+       paddr_t pa;
+       vaddr_t va;
+
+       if (offset < 0 || offset + PAGE_SIZE > sc->sc_framebufsize) {
+               device_printf(sc->sc_dev, "mmap: offset 0x%x, fbsize 0x%x"
+                   " out of range!\n",
+                   (unsigned int)offset, (unsigned int)sc->sc_framebufsize);
+               return -1;
+       }
+
+       va = trunc_page((vaddr_t)sc->sc_framebuf + offset);
+
+       if (pmap_extract(pmap_kernel(), va, &pa) == false) {
+               device_printf(sc->sc_dev, "mmap: pmap_extract failed!\n");
+               return -1;
+       }
+
+       return atop(pa);
 }
 
 static void
@@ -514,6 +561,32 @@
        }
 }
 
+static void
+vncfb_refresh(void *priv)
+{
+       struct vncfb_softc *sc = priv;
+
+       softint_schedule(sc->sc_refresh_sih);
+}
+
+static void
+vncfb_softrefresh(void *priv)
+{
+       struct vncfb_softc *sc = priv;
+
+       if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
+               return;
+
+       /* update the screen */
+       vncfb_update(sc, 0, 0, sc->sc_width, sc->sc_height);
+
+       /* flush the pending drawing op */
+       while (thunk_rfb_poll(&sc->sc_rfb, NULL) > 0)
+               ;
+
+       callout_schedule(&sc->sc_callout, mstohz(VNCFB_REFRESH_INTERVAL));
+}
+
 static int
 vncfb_kbd_enable(void *priv, int on)
 {



Home | Main Index | Thread Index | Old Index