1*c7fb772bSthorpej /* $NetBSD: vncfb.c,v 1.14 2021/08/07 16:19:07 thorpej Exp $ */
24f5a27acSjmcneill
34f5a27acSjmcneill /*-
44f5a27acSjmcneill * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
54f5a27acSjmcneill * All rights reserved.
64f5a27acSjmcneill *
74f5a27acSjmcneill * Redistribution and use in source and binary forms, with or without
84f5a27acSjmcneill * modification, are permitted provided that the following conditions
94f5a27acSjmcneill * are met:
104f5a27acSjmcneill * 1. Redistributions of source code must retain the above copyright
114f5a27acSjmcneill * notice, this list of conditions and the following disclaimer.
124f5a27acSjmcneill * 2. Redistributions in binary form must reproduce the above copyright
134f5a27acSjmcneill * notice, this list of conditions and the following disclaimer in the
144f5a27acSjmcneill * documentation and/or other materials provided with the distribution.
154f5a27acSjmcneill * 3. All advertising materials mentioning features or use of this software
164f5a27acSjmcneill * must display the following acknowledgement:
174f5a27acSjmcneill * This product includes software developed by Jared D. McNeill.
184f5a27acSjmcneill * 4. Neither the name of The NetBSD Foundation nor the names of its
194f5a27acSjmcneill * contributors may be used to endorse or promote products derived
204f5a27acSjmcneill * from this software without specific prior written permission.
214f5a27acSjmcneill *
224f5a27acSjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
234f5a27acSjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
244f5a27acSjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
254f5a27acSjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
264f5a27acSjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
274f5a27acSjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
284f5a27acSjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
294f5a27acSjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
304f5a27acSjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
314f5a27acSjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
324f5a27acSjmcneill * POSSIBILITY OF SUCH DAMAGE.
334f5a27acSjmcneill */
344f5a27acSjmcneill
354f5a27acSjmcneill #include "opt_wsemul.h"
364f5a27acSjmcneill
374f5a27acSjmcneill #include <sys/cdefs.h>
38*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: vncfb.c,v 1.14 2021/08/07 16:19:07 thorpej Exp $");
394f5a27acSjmcneill
404f5a27acSjmcneill #include <sys/param.h>
414f5a27acSjmcneill #include <sys/systm.h>
424f5a27acSjmcneill #include <sys/kernel.h>
434f5a27acSjmcneill #include <sys/device.h>
444f5a27acSjmcneill #include <sys/kmem.h>
454f5a27acSjmcneill
4645276cf9Sjmcneill #include <uvm/uvm_extern.h>
4745276cf9Sjmcneill
484f5a27acSjmcneill #include <dev/wscons/wsconsio.h>
494f5a27acSjmcneill
504f5a27acSjmcneill #include <dev/wscons/wsdisplayvar.h>
514f5a27acSjmcneill #include <dev/wsfont/wsfont.h>
524f5a27acSjmcneill #include <dev/rasops/rasops.h>
534f5a27acSjmcneill #include <dev/wscons/wsdisplay_vconsvar.h>
544f5a27acSjmcneill
554f5a27acSjmcneill #include <dev/wscons/wskbdvar.h>
564f5a27acSjmcneill #include <dev/wscons/wsksymdef.h>
574f5a27acSjmcneill #include <dev/wscons/wsksymvar.h>
584f5a27acSjmcneill
59e3b27f0cSjmcneill #include <dev/wscons/wsmousevar.h>
60e3b27f0cSjmcneill
614f5a27acSjmcneill #include <machine/mainbus.h>
624f5a27acSjmcneill #include <machine/thunk.h>
634f5a27acSjmcneill
6445276cf9Sjmcneill #define VNCFB_REFRESH_INTERVAL 33 /* fb refresh interval when mapped */
6545276cf9Sjmcneill
664f5a27acSjmcneill struct vncfb_fbops {
674f5a27acSjmcneill void (*copycols)(void *, int, int, int, int);
684f5a27acSjmcneill void (*erasecols)(void *, int, int, int, long);
694f5a27acSjmcneill void (*copyrows)(void *, int, int, int);
704f5a27acSjmcneill void (*eraserows)(void *, int, int, long);
714f5a27acSjmcneill void (*putchar)(void *, int, int, u_int, long);
72a91f77bbSjmcneill void (*cursor)(void *, int, int, int);
734f5a27acSjmcneill };
744f5a27acSjmcneill
754f5a27acSjmcneill struct vncfb_softc {
764f5a27acSjmcneill device_t sc_dev;
774f5a27acSjmcneill device_t sc_wskbddev;
78e3b27f0cSjmcneill device_t sc_wsmousedev;
794f5a27acSjmcneill thunk_rfb_t sc_rfb;
804f5a27acSjmcneill unsigned int sc_width;
814f5a27acSjmcneill unsigned int sc_height;
824f5a27acSjmcneill unsigned int sc_depth;
834f5a27acSjmcneill int sc_mode;
8445276cf9Sjmcneill uint8_t * sc_mem;
8545276cf9Sjmcneill size_t sc_memsize;
864f5a27acSjmcneill uint8_t * sc_framebuf;
8745276cf9Sjmcneill size_t sc_framebufsize;
884f5a27acSjmcneill struct vcons_data sc_vd;
894f5a27acSjmcneill struct vncfb_fbops sc_ops;
904f5a27acSjmcneill
914f5a27acSjmcneill int sc_kbd_enable;
92e3b27f0cSjmcneill int sc_mouse_enable;
934f5a27acSjmcneill
94fc3088acSjmcneill void *sc_ih;
954f5a27acSjmcneill void *sc_sih;
9645276cf9Sjmcneill
9745276cf9Sjmcneill callout_t sc_callout;
9845276cf9Sjmcneill void *sc_refresh_sih;
994f5a27acSjmcneill };
1004f5a27acSjmcneill
1014f5a27acSjmcneill static int vncfb_match(device_t, cfdata_t, void *);
1024f5a27acSjmcneill static void vncfb_attach(device_t, device_t, void *);
1034f5a27acSjmcneill
1044f5a27acSjmcneill CFATTACH_DECL_NEW(vncfb, sizeof(struct vncfb_softc),
1054f5a27acSjmcneill vncfb_match, vncfb_attach, NULL, NULL);
1064f5a27acSjmcneill
1074f5a27acSjmcneill static void vncfb_putchar(void *, int, int, u_int, long);
1084f5a27acSjmcneill static void vncfb_copycols(void *, int, int, int, int);
1094f5a27acSjmcneill static void vncfb_erasecols(void *, int, int, int, long);
1104f5a27acSjmcneill static void vncfb_copyrows(void *, int, int, int);
1114f5a27acSjmcneill static void vncfb_eraserows(void *, int, int, long);
112a91f77bbSjmcneill static void vncfb_cursor(void *, int, int, int);
1134f5a27acSjmcneill
1144f5a27acSjmcneill static int vncfb_ioctl(void *, void *, u_long, void *, int, lwp_t *);
1154f5a27acSjmcneill static paddr_t vncfb_mmap(void *, void *, off_t, int);
1164f5a27acSjmcneill
1174f5a27acSjmcneill static void vncfb_init_screen(void *, struct vcons_screen *, int, long *);
1184f5a27acSjmcneill
1194f5a27acSjmcneill static void vncfb_update(struct vncfb_softc *, int, int, int, int);
12032f706abSjmcneill static void vncfb_copyrect(struct vncfb_softc *, int, int, int, int, int, int);
12132f706abSjmcneill static void vncfb_fillrect(struct vncfb_softc *, int, int, int, int, uint32_t);
122fc3088acSjmcneill static int vncfb_intr(void *);
1234f5a27acSjmcneill static void vncfb_softintr(void *);
12445276cf9Sjmcneill static void vncfb_refresh(void *);
12545276cf9Sjmcneill static void vncfb_softrefresh(void *);
1264f5a27acSjmcneill
1274f5a27acSjmcneill static int vncfb_kbd_enable(void *, int);
1284f5a27acSjmcneill static void vncfb_kbd_set_leds(void *, int);
1294f5a27acSjmcneill static int vncfb_kbd_ioctl(void *, u_long, void *, int, lwp_t *);
1304f5a27acSjmcneill
1314f5a27acSjmcneill static void vncfb_kbd_cngetc(void *, u_int *, int *);
1324f5a27acSjmcneill static void vncfb_kbd_cnpollc(void *, int);
133b5566174Sjmcneill static void vncfb_kbd_bell(void *, u_int, u_int, u_int);
1344f5a27acSjmcneill
135e3b27f0cSjmcneill static int vncfb_mouse_enable(void *);
136e3b27f0cSjmcneill static int vncfb_mouse_ioctl(void *, u_long, void *, int, lwp_t *);
137e3b27f0cSjmcneill static void vncfb_mouse_disable(void *);
138e3b27f0cSjmcneill
1394f5a27acSjmcneill static struct vcons_screen vncfb_console_screen;
1404f5a27acSjmcneill
1414f5a27acSjmcneill static struct wsscreen_descr vncfb_defaultscreen = {
1424f5a27acSjmcneill .name = "default",
1434f5a27acSjmcneill .fontwidth = 8,
1444f5a27acSjmcneill .fontheight = 16,
1454f5a27acSjmcneill .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
1464f5a27acSjmcneill };
1474f5a27acSjmcneill
1484f5a27acSjmcneill static const struct wsscreen_descr *vncfb_screens[] = {
1494f5a27acSjmcneill &vncfb_defaultscreen,
1504f5a27acSjmcneill };
1514f5a27acSjmcneill
1524f5a27acSjmcneill static struct wsscreen_list vncfb_screenlist = {
1534f5a27acSjmcneill .screens = vncfb_screens,
1544f5a27acSjmcneill .nscreens = __arraycount(vncfb_screens),
1554f5a27acSjmcneill };
1564f5a27acSjmcneill
1574f5a27acSjmcneill static struct wsdisplay_accessops vncfb_accessops = {
1584f5a27acSjmcneill .ioctl = vncfb_ioctl,
1594f5a27acSjmcneill .mmap = vncfb_mmap,
1604f5a27acSjmcneill };
1614f5a27acSjmcneill
1624f5a27acSjmcneill extern const struct wscons_keydesc vnckbd_keydesctab[];
1634f5a27acSjmcneill
1644f5a27acSjmcneill static const struct wskbd_mapdata vncfb_keymapdata = {
1654f5a27acSjmcneill vnckbd_keydesctab,
1664f5a27acSjmcneill KB_US,
1674f5a27acSjmcneill };
1684f5a27acSjmcneill
1694f5a27acSjmcneill static struct wskbd_accessops vncfb_kbd_accessops = {
1704f5a27acSjmcneill vncfb_kbd_enable,
1714f5a27acSjmcneill vncfb_kbd_set_leds,
1724f5a27acSjmcneill vncfb_kbd_ioctl,
1734f5a27acSjmcneill };
1744f5a27acSjmcneill
1754f5a27acSjmcneill static const struct wskbd_consops vncfb_kbd_consops = {
1764f5a27acSjmcneill vncfb_kbd_cngetc,
1774f5a27acSjmcneill vncfb_kbd_cnpollc,
178b5566174Sjmcneill vncfb_kbd_bell,
1794f5a27acSjmcneill };
1804f5a27acSjmcneill
181e3b27f0cSjmcneill static const struct wsmouse_accessops vncfb_mouse_accessops = {
182e3b27f0cSjmcneill vncfb_mouse_enable,
183e3b27f0cSjmcneill vncfb_mouse_ioctl,
184e3b27f0cSjmcneill vncfb_mouse_disable,
185e3b27f0cSjmcneill };
186e3b27f0cSjmcneill
1874f5a27acSjmcneill static int
vncfb_match(device_t parent,cfdata_t match,void * priv)1884f5a27acSjmcneill vncfb_match(device_t parent, cfdata_t match, void *priv)
1894f5a27acSjmcneill {
1904f5a27acSjmcneill struct thunkbus_attach_args *taa = priv;
1914f5a27acSjmcneill
1924f5a27acSjmcneill return taa->taa_type == THUNKBUS_TYPE_VNCFB;
1934f5a27acSjmcneill }
1944f5a27acSjmcneill
1954f5a27acSjmcneill static void
vncfb_attach(device_t parent,device_t self,void * priv)1964f5a27acSjmcneill vncfb_attach(device_t parent, device_t self, void *priv)
1974f5a27acSjmcneill {
1984f5a27acSjmcneill struct vncfb_softc *sc = device_private(self);
1994f5a27acSjmcneill struct thunkbus_attach_args *taa = priv;
2004f5a27acSjmcneill struct wsemuldisplaydev_attach_args waa;
2014f5a27acSjmcneill struct wskbddev_attach_args kaa;
202e3b27f0cSjmcneill struct wsmousedev_attach_args maa;
2034f5a27acSjmcneill struct rasops_info *ri;
2044f5a27acSjmcneill unsigned long defattr;
2054f5a27acSjmcneill
2064f5a27acSjmcneill sc->sc_dev = self;
2074f5a27acSjmcneill sc->sc_width = taa->u.vnc.width;
2084f5a27acSjmcneill sc->sc_height = taa->u.vnc.height;
2094f5a27acSjmcneill sc->sc_depth = 32;
2104f5a27acSjmcneill sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
2114f5a27acSjmcneill #if notyet
2124f5a27acSjmcneill sc->sc_sockfd = thunk_vnc_open_socket(taa->u.vnc.port);
2134f5a27acSjmcneill if (sc->sc_sockfd == -1)
2144f5a27acSjmcneill panic("couldn't open VNC socket");
2154f5a27acSjmcneill #endif
2164f5a27acSjmcneill
21745276cf9Sjmcneill sc->sc_framebufsize = sc->sc_width * sc->sc_height * (sc->sc_depth / 8);
21845276cf9Sjmcneill sc->sc_memsize = sc->sc_framebufsize + PAGE_SIZE;
21945276cf9Sjmcneill
22045276cf9Sjmcneill sc->sc_mem = kmem_zalloc(sc->sc_memsize, KM_SLEEP);
22145276cf9Sjmcneill sc->sc_framebuf = (void *)round_page((vaddr_t)sc->sc_mem);
2224f5a27acSjmcneill
2234f5a27acSjmcneill aprint_naive("\n");
2244f5a27acSjmcneill aprint_normal(": %ux%u %ubpp (port %u)\n",
2254f5a27acSjmcneill sc->sc_width, sc->sc_height, sc->sc_depth, taa->u.vnc.port);
2264f5a27acSjmcneill
2274f5a27acSjmcneill sc->sc_rfb.width = sc->sc_width;
2284f5a27acSjmcneill sc->sc_rfb.height = sc->sc_height;
2294f5a27acSjmcneill sc->sc_rfb.depth = sc->sc_depth;
2304f5a27acSjmcneill sc->sc_rfb.framebuf = sc->sc_framebuf;
2314f5a27acSjmcneill snprintf(sc->sc_rfb.name, sizeof(sc->sc_rfb.name),
2324f5a27acSjmcneill "NetBSD/usermode %d.%d.%d",
2334f5a27acSjmcneill __NetBSD_Version__ / 100000000,
2344f5a27acSjmcneill (__NetBSD_Version__ / 1000000) % 100,
2354f5a27acSjmcneill (__NetBSD_Version__ / 100) % 100);
2364f5a27acSjmcneill if (thunk_rfb_open(&sc->sc_rfb, taa->u.vnc.port) != 0)
2374f5a27acSjmcneill panic("couldn't open rfb server");
2384f5a27acSjmcneill
2394f5a27acSjmcneill sc->sc_sih = softint_establish(SOFTINT_SERIAL, vncfb_softintr, sc);
240fc3088acSjmcneill sc->sc_ih = sigio_intr_establish(vncfb_intr, sc);
2414f5a27acSjmcneill
24245276cf9Sjmcneill sc->sc_refresh_sih = softint_establish(SOFTINT_SERIAL,
24345276cf9Sjmcneill vncfb_softrefresh, sc);
24445276cf9Sjmcneill
24545276cf9Sjmcneill callout_init(&sc->sc_callout, 0);
24645276cf9Sjmcneill callout_setfunc(&sc->sc_callout, vncfb_refresh, sc);
24745276cf9Sjmcneill
2484f5a27acSjmcneill vcons_init(&sc->sc_vd, sc, &vncfb_defaultscreen, &vncfb_accessops);
2494f5a27acSjmcneill sc->sc_vd.init_screen = vncfb_init_screen;
2504f5a27acSjmcneill
2514f5a27acSjmcneill ri = &vncfb_console_screen.scr_ri;
2524f5a27acSjmcneill vcons_init_screen(&sc->sc_vd, &vncfb_console_screen, 1, &defattr);
2534f5a27acSjmcneill vncfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
2544f5a27acSjmcneill vncfb_defaultscreen.textops = &ri->ri_ops;
2554f5a27acSjmcneill vncfb_defaultscreen.capabilities = ri->ri_caps;
2564f5a27acSjmcneill vncfb_defaultscreen.nrows = ri->ri_rows;
2574f5a27acSjmcneill vncfb_defaultscreen.ncols = ri->ri_cols;
2584f5a27acSjmcneill wsdisplay_cnattach(&vncfb_defaultscreen, ri, 0, 0, defattr);
2594f5a27acSjmcneill
2604f5a27acSjmcneill vcons_replay_msgbuf(&vncfb_console_screen);
2614f5a27acSjmcneill
2624f5a27acSjmcneill waa.console = true;
2634f5a27acSjmcneill waa.scrdata = &vncfb_screenlist;
2644f5a27acSjmcneill waa.accessops = &vncfb_accessops;
2654f5a27acSjmcneill waa.accesscookie = &sc->sc_vd;
2664f5a27acSjmcneill
267*c7fb772bSthorpej config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
2684f5a27acSjmcneill
2694f5a27acSjmcneill wskbd_cnattach(&vncfb_kbd_consops, sc, &vncfb_keymapdata);
2704f5a27acSjmcneill
2714f5a27acSjmcneill kaa.console = true;
2724f5a27acSjmcneill kaa.keymap = &vncfb_keymapdata;
2734f5a27acSjmcneill kaa.accessops = &vncfb_kbd_accessops;
2744f5a27acSjmcneill kaa.accesscookie = sc;
2754f5a27acSjmcneill
2762685996bSthorpej sc->sc_wskbddev = config_found(self, &kaa, wskbddevprint,
277*c7fb772bSthorpej CFARGS(.iattr = "wskbddev"));
278e3b27f0cSjmcneill
279e3b27f0cSjmcneill maa.accessops = &vncfb_mouse_accessops;
280e3b27f0cSjmcneill maa.accesscookie = sc;
281e3b27f0cSjmcneill
2822685996bSthorpej sc->sc_wsmousedev = config_found(self, &maa, wsmousedevprint,
283*c7fb772bSthorpej CFARGS(.iattr = "wsmousedev"));
2844f5a27acSjmcneill }
2854f5a27acSjmcneill
2864f5a27acSjmcneill static void
vncfb_init_screen(void * priv,struct vcons_screen * scr,int existing,long * defattr)2874f5a27acSjmcneill vncfb_init_screen(void *priv, struct vcons_screen *scr, int existing,
2884f5a27acSjmcneill long *defattr)
2894f5a27acSjmcneill {
2904f5a27acSjmcneill struct vncfb_softc *sc = priv;
2914f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
2924f5a27acSjmcneill struct rasops_info *ri = &scr->scr_ri;
2934f5a27acSjmcneill
2944f5a27acSjmcneill ri->ri_width = sc->sc_width;
2954f5a27acSjmcneill ri->ri_height = sc->sc_height;
2964f5a27acSjmcneill ri->ri_depth = sc->sc_depth;
2974f5a27acSjmcneill ri->ri_stride = sc->sc_width * ri->ri_depth / 8;
2984f5a27acSjmcneill ri->ri_bits = sc->sc_framebuf;
2994f5a27acSjmcneill ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
3004f5a27acSjmcneill if (existing)
3014f5a27acSjmcneill ri->ri_flg |= RI_CLEAR;
3024f5a27acSjmcneill
3034f5a27acSjmcneill rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
3044f5a27acSjmcneill ri->ri_caps = WSSCREEN_WSCOLORS;
3054f5a27acSjmcneill rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
3064f5a27acSjmcneill sc->sc_width / ri->ri_font->fontwidth);
3074f5a27acSjmcneill
3084f5a27acSjmcneill ri->ri_hw = scr;
3094f5a27acSjmcneill
3104f5a27acSjmcneill ops->putchar = ri->ri_ops.putchar;
3114f5a27acSjmcneill ops->copyrows = ri->ri_ops.copyrows;
3124f5a27acSjmcneill ops->eraserows = ri->ri_ops.eraserows;
3134f5a27acSjmcneill ops->copycols = ri->ri_ops.copycols;
3144f5a27acSjmcneill ops->erasecols = ri->ri_ops.erasecols;
315a91f77bbSjmcneill ops->cursor = ri->ri_ops.cursor;
3164f5a27acSjmcneill
3174f5a27acSjmcneill ri->ri_ops.copyrows = vncfb_copyrows;
3184f5a27acSjmcneill ri->ri_ops.copycols = vncfb_copycols;
3194f5a27acSjmcneill ri->ri_ops.eraserows = vncfb_eraserows;
3204f5a27acSjmcneill ri->ri_ops.erasecols = vncfb_erasecols;
3214f5a27acSjmcneill ri->ri_ops.putchar = vncfb_putchar;
322a91f77bbSjmcneill ri->ri_ops.cursor = vncfb_cursor;
3234f5a27acSjmcneill }
3244f5a27acSjmcneill
3254f5a27acSjmcneill static void
vncfb_putchar(void * priv,int row,int col,u_int c,long attr)3264f5a27acSjmcneill vncfb_putchar(void *priv, int row, int col, u_int c, long attr)
3274f5a27acSjmcneill {
3284f5a27acSjmcneill struct rasops_info *ri = priv;
3294f5a27acSjmcneill struct vcons_screen *scr = ri->ri_hw;
3304f5a27acSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
3314f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
3324f5a27acSjmcneill int x, y, w, h;
3334f5a27acSjmcneill
3344f5a27acSjmcneill ops->putchar(ri, row, col, c, attr);
3354f5a27acSjmcneill
3364f5a27acSjmcneill x = ri->ri_xorigin + (col * ri->ri_font->fontwidth);
3374f5a27acSjmcneill y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
3384f5a27acSjmcneill w = ri->ri_font->fontwidth;
3394f5a27acSjmcneill h = ri->ri_font->fontheight;
3404f5a27acSjmcneill
3414f5a27acSjmcneill vncfb_update(sc, x, y, w, h);
3424f5a27acSjmcneill }
3434f5a27acSjmcneill
3444f5a27acSjmcneill static void
vncfb_copycols(void * priv,int row,int srccol,int dstcol,int ncols)3454f5a27acSjmcneill vncfb_copycols(void *priv, int row, int srccol, int dstcol, int ncols)
3464f5a27acSjmcneill {
3474f5a27acSjmcneill struct rasops_info *ri = priv;
3484f5a27acSjmcneill struct vcons_screen *scr = ri->ri_hw;
3494f5a27acSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
3504f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
3514f5a27acSjmcneill int x, y, w, h;
3524f5a27acSjmcneill
3534f5a27acSjmcneill ops->copycols(ri, row, srccol, dstcol, ncols);
3544f5a27acSjmcneill
3554f5a27acSjmcneill y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
3564f5a27acSjmcneill h = ri->ri_font->fontheight;
3574f5a27acSjmcneill if (srccol < dstcol) {
3584f5a27acSjmcneill x = ri->ri_xorigin + (srccol * ri->ri_font->fontwidth);
3594f5a27acSjmcneill w = (dstcol - srccol) * ri->ri_font->fontwidth;
3604f5a27acSjmcneill
3614f5a27acSjmcneill } else {
3624f5a27acSjmcneill x = ri->ri_xorigin + (dstcol * ri->ri_font->fontwidth);
3634f5a27acSjmcneill w = (srccol - dstcol) * ri->ri_font->fontwidth;
3644f5a27acSjmcneill }
3654f5a27acSjmcneill
3664f5a27acSjmcneill vncfb_update(sc, x, y, w, h);
3674f5a27acSjmcneill }
3684f5a27acSjmcneill
3694f5a27acSjmcneill static void
vncfb_erasecols(void * priv,int row,int startcol,int ncols,long fillattr)3704f5a27acSjmcneill vncfb_erasecols(void *priv, int row, int startcol, int ncols, long fillattr)
3714f5a27acSjmcneill {
3724f5a27acSjmcneill struct rasops_info *ri = priv;
3734f5a27acSjmcneill struct vcons_screen *scr = ri->ri_hw;
3744f5a27acSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
3754f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
37632f706abSjmcneill int x, y, w, h, c;
3774f5a27acSjmcneill
3784f5a27acSjmcneill ops->erasecols(ri, row, startcol, ncols, fillattr);
3794f5a27acSjmcneill
3804f5a27acSjmcneill y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
3814f5a27acSjmcneill h = ri->ri_font->fontheight;
3824f5a27acSjmcneill x = ri->ri_xorigin + (startcol * ri->ri_font->fontwidth);
3834f5a27acSjmcneill w = ncols * ri->ri_font->fontwidth;
38432f706abSjmcneill c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff;
3854f5a27acSjmcneill
38632f706abSjmcneill vncfb_fillrect(sc, x, y, w, h, c);
3874f5a27acSjmcneill }
3884f5a27acSjmcneill
3894f5a27acSjmcneill static void
vncfb_copyrows(void * priv,int srcrow,int dstrow,int nrows)3904f5a27acSjmcneill vncfb_copyrows(void *priv, int srcrow, int dstrow, int nrows)
3914f5a27acSjmcneill {
3924f5a27acSjmcneill struct rasops_info *ri = priv;
3934f5a27acSjmcneill struct vcons_screen *scr = ri->ri_hw;
3944f5a27acSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
3954f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
3964b4a4e64Sreinoud int x, y, w, h, srcx, srcy;
3974b4a4e64Sreinoud int fontheight;
3984f5a27acSjmcneill
39932f706abSjmcneill /* barrier */
40032f706abSjmcneill while (sc->sc_rfb.nupdates > 0)
401869f56b4Sjmcneill if (thunk_rfb_poll(&sc->sc_rfb, NULL) == -1)
402869f56b4Sjmcneill break;
40332f706abSjmcneill
4044f5a27acSjmcneill ops->copyrows(ri, srcrow, dstrow, nrows);
4054f5a27acSjmcneill
4064b4a4e64Sreinoud fontheight = ri->ri_font->fontheight;
4074f5a27acSjmcneill x = ri->ri_xorigin;
4084b4a4e64Sreinoud y = ri->ri_yorigin + dstrow * fontheight;
4094f5a27acSjmcneill w = ri->ri_width;
4104b4a4e64Sreinoud h = nrows * fontheight;
4114f5a27acSjmcneill
4124b4a4e64Sreinoud srcx = ri->ri_xorigin;
4134b4a4e64Sreinoud srcy = ri->ri_yorigin + srcrow * fontheight;
4144b4a4e64Sreinoud
4154b4a4e64Sreinoud vncfb_copyrect(sc, x, y, w, h, srcx, srcy);
4164f5a27acSjmcneill }
4174f5a27acSjmcneill
4184f5a27acSjmcneill static void
vncfb_eraserows(void * priv,int row,int nrows,long fillattr)4194f5a27acSjmcneill vncfb_eraserows(void *priv, int row, int nrows, long fillattr)
4204f5a27acSjmcneill {
4214f5a27acSjmcneill struct rasops_info *ri = priv;
4224f5a27acSjmcneill struct vcons_screen *scr = ri->ri_hw;
4234f5a27acSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
4244f5a27acSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
42532f706abSjmcneill int x, y, w, h, c;
4264f5a27acSjmcneill
4274f5a27acSjmcneill ops->eraserows(ri, row, nrows, fillattr);
4284f5a27acSjmcneill
4294f5a27acSjmcneill y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
4304f5a27acSjmcneill h = nrows * ri->ri_font->fontheight;
4314f5a27acSjmcneill x = ri->ri_xorigin;
4324f5a27acSjmcneill w = ri->ri_width;
43332f706abSjmcneill c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff;
4344f5a27acSjmcneill
43532f706abSjmcneill vncfb_fillrect(sc, x, y, w, h, c);
4364f5a27acSjmcneill }
4374f5a27acSjmcneill
438a91f77bbSjmcneill static void
vncfb_cursor(void * priv,int on,int row,int col)439a91f77bbSjmcneill vncfb_cursor(void *priv, int on, int row, int col)
440a91f77bbSjmcneill {
441a91f77bbSjmcneill struct rasops_info *ri = priv;
442a91f77bbSjmcneill struct vcons_screen *scr = ri->ri_hw;
443a91f77bbSjmcneill struct vncfb_softc *sc = scr->scr_cookie;
444a91f77bbSjmcneill struct vncfb_fbops *ops = &sc->sc_ops;
445a91f77bbSjmcneill int ox, oy, x, y, w, h;
446a91f77bbSjmcneill
447a91f77bbSjmcneill w = ri->ri_font->fontwidth;
448a91f77bbSjmcneill h = ri->ri_font->fontheight;
449a91f77bbSjmcneill
450a91f77bbSjmcneill ox = ri->ri_ccol * w + ri->ri_xorigin;
451a91f77bbSjmcneill oy = ri->ri_crow * h + ri->ri_yorigin;
452a91f77bbSjmcneill
453a91f77bbSjmcneill ops->cursor(ri, on, row, col);
454a91f77bbSjmcneill
455a91f77bbSjmcneill x = ri->ri_ccol * w + ri->ri_xorigin;
456a91f77bbSjmcneill y = ri->ri_crow * h + ri->ri_yorigin;
457a91f77bbSjmcneill
458a91f77bbSjmcneill vncfb_update(sc, ox, oy, w, h);
459a91f77bbSjmcneill vncfb_update(sc, x, y, w, h);
460a91f77bbSjmcneill }
461a91f77bbSjmcneill
4624f5a27acSjmcneill static int
vncfb_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,lwp_t * l)4634f5a27acSjmcneill vncfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
4644f5a27acSjmcneill {
4654f5a27acSjmcneill struct vcons_data *vd = v;
4664f5a27acSjmcneill struct vncfb_softc *sc = vd->cookie;
4674f5a27acSjmcneill struct wsdisplay_fbinfo *wdf;
4684f5a27acSjmcneill struct vcons_screen *ms = vd->active;
4694f5a27acSjmcneill int new_mode;
4704f5a27acSjmcneill
4714f5a27acSjmcneill switch (cmd) {
4724f5a27acSjmcneill case WSDISPLAYIO_GTYPE:
4734f5a27acSjmcneill *(u_int *)data = WSDISPLAY_TYPE_VNC;
4744f5a27acSjmcneill return 0;
4754f5a27acSjmcneill case WSDISPLAYIO_GINFO:
4764f5a27acSjmcneill wdf = data;
4774f5a27acSjmcneill wdf->height = ms->scr_ri.ri_height;
4784f5a27acSjmcneill wdf->width = ms->scr_ri.ri_width;
4794f5a27acSjmcneill wdf->depth = ms->scr_ri.ri_depth;
4804f5a27acSjmcneill wdf->cmsize = 256;
4814f5a27acSjmcneill return 0;
48245276cf9Sjmcneill case WSDISPLAYIO_LINEBYTES:
48345276cf9Sjmcneill *(u_int *)data = sc->sc_width * (sc->sc_depth / 8);
48445276cf9Sjmcneill return 0;
4854f5a27acSjmcneill case WSDISPLAYIO_SMODE:
4864f5a27acSjmcneill new_mode = *(int *)data;
4874f5a27acSjmcneill if (sc->sc_mode != new_mode) {
4884f5a27acSjmcneill sc->sc_mode = new_mode;
48945276cf9Sjmcneill if (new_mode == WSDISPLAYIO_MODE_EMUL) {
49045276cf9Sjmcneill callout_halt(&sc->sc_callout, NULL);
4914f5a27acSjmcneill vcons_redraw_screen(ms);
49245276cf9Sjmcneill } else {
49345276cf9Sjmcneill callout_schedule(&sc->sc_callout, 1);
49445276cf9Sjmcneill }
4954f5a27acSjmcneill }
4964f5a27acSjmcneill return 0;
4974f5a27acSjmcneill default:
4984f5a27acSjmcneill return EPASSTHROUGH;
4994f5a27acSjmcneill }
5004f5a27acSjmcneill }
5014f5a27acSjmcneill
5024f5a27acSjmcneill static paddr_t
vncfb_mmap(void * v,void * vs,off_t offset,int prot)5034f5a27acSjmcneill vncfb_mmap(void *v, void *vs, off_t offset, int prot)
5044f5a27acSjmcneill {
50545276cf9Sjmcneill struct vcons_data *vd = v;
50645276cf9Sjmcneill struct vncfb_softc *sc = vd->cookie;
50745276cf9Sjmcneill paddr_t pa;
50845276cf9Sjmcneill vaddr_t va;
50945276cf9Sjmcneill
51031469ba1Sjmcneill if (offset < 0 || offset >= sc->sc_framebufsize) {
51145276cf9Sjmcneill device_printf(sc->sc_dev, "mmap: offset 0x%x, fbsize 0x%x"
51245276cf9Sjmcneill " out of range!\n",
51345276cf9Sjmcneill (unsigned int)offset, (unsigned int)sc->sc_framebufsize);
5144f5a27acSjmcneill return -1;
5154f5a27acSjmcneill }
5164f5a27acSjmcneill
51745276cf9Sjmcneill va = trunc_page((vaddr_t)sc->sc_framebuf + offset);
51845276cf9Sjmcneill
51945276cf9Sjmcneill if (pmap_extract(pmap_kernel(), va, &pa) == false) {
52045276cf9Sjmcneill device_printf(sc->sc_dev, "mmap: pmap_extract failed!\n");
52145276cf9Sjmcneill return -1;
52245276cf9Sjmcneill }
52345276cf9Sjmcneill
52445276cf9Sjmcneill return atop(pa);
52545276cf9Sjmcneill }
52645276cf9Sjmcneill
5274f5a27acSjmcneill static void
vncfb_update(struct vncfb_softc * sc,int x,int y,int w,int h)5284f5a27acSjmcneill vncfb_update(struct vncfb_softc *sc, int x, int y, int w, int h)
5294f5a27acSjmcneill {
5304f5a27acSjmcneill thunk_rfb_update(&sc->sc_rfb, x, y, w, h);
531fc3088acSjmcneill softint_schedule(sc->sc_sih);
5324f5a27acSjmcneill }
5334f5a27acSjmcneill
5344b4a4e64Sreinoud static void
vncfb_copyrect(struct vncfb_softc * sc,int x,int y,int w,int h,int srcx,int srcy)5354b4a4e64Sreinoud vncfb_copyrect(struct vncfb_softc *sc, int x, int y, int w, int h,
5364b4a4e64Sreinoud int srcx, int srcy)
5374b4a4e64Sreinoud {
5384b4a4e64Sreinoud thunk_rfb_copyrect(&sc->sc_rfb, x, y, w, h, srcx, srcy);
5394b4a4e64Sreinoud softint_schedule(sc->sc_sih);
5404b4a4e64Sreinoud }
5414b4a4e64Sreinoud
54232f706abSjmcneill static void
vncfb_fillrect(struct vncfb_softc * sc,int x,int y,int w,int h,uint32_t c)54332f706abSjmcneill vncfb_fillrect(struct vncfb_softc *sc, int x, int y, int w, int h, uint32_t c)
54432f706abSjmcneill {
54532f706abSjmcneill
54632f706abSjmcneill thunk_rfb_fillrect(&sc->sc_rfb, x, y, w, h, (uint8_t *)&c);
54732f706abSjmcneill softint_schedule(sc->sc_sih);
54832f706abSjmcneill }
54932f706abSjmcneill
550fc3088acSjmcneill static int
vncfb_intr(void * priv)551fc3088acSjmcneill vncfb_intr(void *priv)
5524f5a27acSjmcneill {
5534f5a27acSjmcneill struct vncfb_softc *sc = priv;
5544f5a27acSjmcneill
5554f5a27acSjmcneill softint_schedule(sc->sc_sih);
556fc3088acSjmcneill
557fc3088acSjmcneill return 0;
5584f5a27acSjmcneill }
5594f5a27acSjmcneill
5604f5a27acSjmcneill static void
vncfb_softintr(void * priv)5614f5a27acSjmcneill vncfb_softintr(void *priv)
5624f5a27acSjmcneill {
5634f5a27acSjmcneill struct vncfb_softc *sc = priv;
5644f5a27acSjmcneill thunk_rfb_event_t event;
5654f5a27acSjmcneill int s;
5664f5a27acSjmcneill
5674f5a27acSjmcneill while (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) {
5684f5a27acSjmcneill switch (event.message_type) {
5694f5a27acSjmcneill case THUNK_RFB_KEY_EVENT:
5704f5a27acSjmcneill s = spltty();
5714f5a27acSjmcneill wskbd_input(sc->sc_wskbddev,
5724f5a27acSjmcneill event.data.key_event.down_flag ?
5734f5a27acSjmcneill WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP,
5744f5a27acSjmcneill event.data.key_event.keysym & 0xfff);
5754f5a27acSjmcneill splx(s);
5764f5a27acSjmcneill break;
577e3b27f0cSjmcneill case THUNK_RFB_POINTER_EVENT:
578e3b27f0cSjmcneill s = spltty();
579e3b27f0cSjmcneill wsmouse_input(sc->sc_wsmousedev,
580e3b27f0cSjmcneill event.data.pointer_event.button_mask,
581e3b27f0cSjmcneill event.data.pointer_event.absx,
582e3b27f0cSjmcneill event.data.pointer_event.absy,
583e3b27f0cSjmcneill 0, 0,
584e3b27f0cSjmcneill WSMOUSE_INPUT_ABSOLUTE_X|WSMOUSE_INPUT_ABSOLUTE_Y);
585e3b27f0cSjmcneill splx(s);
5864f5a27acSjmcneill default:
5874f5a27acSjmcneill break;
5884f5a27acSjmcneill }
5894f5a27acSjmcneill }
5904f5a27acSjmcneill }
5914f5a27acSjmcneill
59245276cf9Sjmcneill static void
vncfb_refresh(void * priv)59345276cf9Sjmcneill vncfb_refresh(void *priv)
59445276cf9Sjmcneill {
59545276cf9Sjmcneill struct vncfb_softc *sc = priv;
59645276cf9Sjmcneill
59745276cf9Sjmcneill softint_schedule(sc->sc_refresh_sih);
59845276cf9Sjmcneill }
59945276cf9Sjmcneill
60045276cf9Sjmcneill static void
vncfb_softrefresh(void * priv)60145276cf9Sjmcneill vncfb_softrefresh(void *priv)
60245276cf9Sjmcneill {
60345276cf9Sjmcneill struct vncfb_softc *sc = priv;
60445276cf9Sjmcneill
60545276cf9Sjmcneill if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
60645276cf9Sjmcneill return;
60745276cf9Sjmcneill
60845276cf9Sjmcneill /* update the screen */
60945276cf9Sjmcneill vncfb_update(sc, 0, 0, sc->sc_width, sc->sc_height);
61045276cf9Sjmcneill
61145276cf9Sjmcneill /* flush the pending drawing op */
61245276cf9Sjmcneill while (thunk_rfb_poll(&sc->sc_rfb, NULL) > 0)
61345276cf9Sjmcneill ;
61445276cf9Sjmcneill
61545276cf9Sjmcneill callout_schedule(&sc->sc_callout, mstohz(VNCFB_REFRESH_INTERVAL));
61645276cf9Sjmcneill }
61745276cf9Sjmcneill
6184f5a27acSjmcneill static int
vncfb_kbd_enable(void * priv,int on)6194f5a27acSjmcneill vncfb_kbd_enable(void *priv, int on)
6204f5a27acSjmcneill {
6214f5a27acSjmcneill struct vncfb_softc *sc = priv;
6224f5a27acSjmcneill
6234f5a27acSjmcneill sc->sc_kbd_enable = on;
6244f5a27acSjmcneill
6254f5a27acSjmcneill return 0;
6264f5a27acSjmcneill }
6274f5a27acSjmcneill
6284f5a27acSjmcneill static void
vncfb_kbd_set_leds(void * priv,int leds)6294f5a27acSjmcneill vncfb_kbd_set_leds(void *priv, int leds)
6304f5a27acSjmcneill {
6314f5a27acSjmcneill }
6324f5a27acSjmcneill
6334f5a27acSjmcneill static int
vncfb_kbd_ioctl(void * priv,u_long cmd,void * data,int flag,lwp_t * l)6344f5a27acSjmcneill vncfb_kbd_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l)
6354f5a27acSjmcneill {
636b5566174Sjmcneill struct wskbd_bell_data *bd;
637b5566174Sjmcneill
6384f5a27acSjmcneill switch (cmd) {
6394f5a27acSjmcneill case WSKBDIO_GTYPE:
6404f5a27acSjmcneill *(int *)data = WSKBD_TYPE_RFB;
6414f5a27acSjmcneill return 0;
642b5566174Sjmcneill case WSKBDIO_COMPLEXBELL:
643b5566174Sjmcneill bd = data;
644b5566174Sjmcneill vncfb_kbd_bell(priv, bd->pitch, bd->period, bd->volume);
645b5566174Sjmcneill return 0;
6464f5a27acSjmcneill default:
6474f5a27acSjmcneill return EPASSTHROUGH;
6484f5a27acSjmcneill }
6494f5a27acSjmcneill }
6504f5a27acSjmcneill
6514f5a27acSjmcneill static void
vncfb_kbd_cngetc(void * priv,u_int * type,int * data)6524f5a27acSjmcneill vncfb_kbd_cngetc(void *priv, u_int *type, int *data)
6534f5a27acSjmcneill {
654e5172552Sjmcneill struct vncfb_softc *sc = priv;
655e5172552Sjmcneill thunk_rfb_event_t event;
656e5172552Sjmcneill
657e5172552Sjmcneill for (;;) {
658e5172552Sjmcneill if (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) {
659e5172552Sjmcneill if (event.message_type == THUNK_RFB_KEY_EVENT) {
660e5172552Sjmcneill *type = event.data.key_event.down_flag ?
661e5172552Sjmcneill WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
662e5172552Sjmcneill *data = event.data.key_event.keysym & 0xfff;
663e5172552Sjmcneill return;
664e5172552Sjmcneill }
665e5172552Sjmcneill }
666e5172552Sjmcneill }
6674f5a27acSjmcneill }
6684f5a27acSjmcneill
6694f5a27acSjmcneill static void
vncfb_kbd_cnpollc(void * priv,int on)6704f5a27acSjmcneill vncfb_kbd_cnpollc(void *priv, int on)
6714f5a27acSjmcneill {
672e5172552Sjmcneill struct vncfb_softc *sc = priv;
673e5172552Sjmcneill
674e5172552Sjmcneill if (!on) {
675e5172552Sjmcneill vncfb_intr(sc);
676e5172552Sjmcneill }
6774f5a27acSjmcneill }
678b5566174Sjmcneill
679b5566174Sjmcneill static void
vncfb_kbd_bell(void * priv,u_int pitch,u_int period,u_int volume)680b5566174Sjmcneill vncfb_kbd_bell(void *priv, u_int pitch, u_int period, u_int volume)
681b5566174Sjmcneill {
682b5566174Sjmcneill struct vncfb_softc *sc = priv;
683b5566174Sjmcneill
684b5566174Sjmcneill thunk_rfb_bell(&sc->sc_rfb);
685b5566174Sjmcneill softint_schedule(sc->sc_sih);
686b5566174Sjmcneill }
687e3b27f0cSjmcneill
688e3b27f0cSjmcneill static int
vncfb_mouse_enable(void * priv)689e3b27f0cSjmcneill vncfb_mouse_enable(void *priv)
690e3b27f0cSjmcneill {
691e3b27f0cSjmcneill struct vncfb_softc *sc = priv;
692e3b27f0cSjmcneill
693e3b27f0cSjmcneill sc->sc_mouse_enable = 1;
694e3b27f0cSjmcneill
695e3b27f0cSjmcneill return 0;
696e3b27f0cSjmcneill }
697e3b27f0cSjmcneill
698e3b27f0cSjmcneill static int
vncfb_mouse_ioctl(void * priv,u_long cmd,void * data,int flag,lwp_t * l)699e3b27f0cSjmcneill vncfb_mouse_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l)
700e3b27f0cSjmcneill {
701e3b27f0cSjmcneill switch (cmd) {
702e3b27f0cSjmcneill case WSMOUSEIO_GTYPE:
703e3b27f0cSjmcneill *(u_int *)data = WSMOUSE_TYPE_PSEUDO;
704e3b27f0cSjmcneill return 0;
705e3b27f0cSjmcneill default:
706e3b27f0cSjmcneill return EPASSTHROUGH;
707e3b27f0cSjmcneill }
708e3b27f0cSjmcneill }
709e3b27f0cSjmcneill
710e3b27f0cSjmcneill static void
vncfb_mouse_disable(void * priv)711e3b27f0cSjmcneill vncfb_mouse_disable(void *priv)
712e3b27f0cSjmcneill {
713e3b27f0cSjmcneill struct vncfb_softc *sc = priv;
714e3b27f0cSjmcneill
715e3b27f0cSjmcneill sc->sc_mouse_enable = 0;
716e3b27f0cSjmcneill }
717