xref: /freebsd/usr.sbin/bhyve/pci_fbuf.c (revision f4d34383f924e0c0557d0c09eb97430b8f5347d6)
12cf9911fSPeter Grehan /*-
22cf9911fSPeter Grehan  * Copyright (c) 2015 Nahanni Systems, Inc.
32cf9911fSPeter Grehan  * All rights reserved.
42cf9911fSPeter Grehan  *
52cf9911fSPeter Grehan  * Redistribution and use in source and binary forms, with or without
62cf9911fSPeter Grehan  * modification, are permitted provided that the following conditions
72cf9911fSPeter Grehan  * are met:
82cf9911fSPeter Grehan  * 1. Redistributions of source code must retain the above copyright
92cf9911fSPeter Grehan  *    notice, this list of conditions and the following disclaimer.
102cf9911fSPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
112cf9911fSPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
122cf9911fSPeter Grehan  *    documentation and/or other materials provided with the distribution.
132cf9911fSPeter Grehan  *
142cf9911fSPeter Grehan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
152cf9911fSPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162cf9911fSPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172cf9911fSPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182cf9911fSPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192cf9911fSPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202cf9911fSPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212cf9911fSPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222cf9911fSPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232cf9911fSPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242cf9911fSPeter Grehan  * SUCH DAMAGE.
252cf9911fSPeter Grehan  *
262cf9911fSPeter Grehan  * $FreeBSD$
272cf9911fSPeter Grehan  */
282cf9911fSPeter Grehan 
292cf9911fSPeter Grehan #include <sys/cdefs.h>
302cf9911fSPeter Grehan __FBSDID("$FreeBSD$");
312cf9911fSPeter Grehan 
322cf9911fSPeter Grehan #include <sys/types.h>
332cf9911fSPeter Grehan #include <sys/mman.h>
342cf9911fSPeter Grehan 
352cf9911fSPeter Grehan #include <machine/vmm.h>
362cf9911fSPeter Grehan #include <vmmapi.h>
372cf9911fSPeter Grehan 
382cf9911fSPeter Grehan #include <stdio.h>
392cf9911fSPeter Grehan #include <stdlib.h>
402cf9911fSPeter Grehan #include <string.h>
412cf9911fSPeter Grehan 
422cf9911fSPeter Grehan #include <errno.h>
432cf9911fSPeter Grehan #include <unistd.h>
442cf9911fSPeter Grehan 
452cf9911fSPeter Grehan #include "bhyvegc.h"
462cf9911fSPeter Grehan #include "bhyverun.h"
472cf9911fSPeter Grehan #include "console.h"
482cf9911fSPeter Grehan #include "inout.h"
492cf9911fSPeter Grehan #include "pci_emul.h"
502cf9911fSPeter Grehan #include "rfb.h"
512cf9911fSPeter Grehan #include "vga.h"
522cf9911fSPeter Grehan 
532cf9911fSPeter Grehan /*
542cf9911fSPeter Grehan  * bhyve Framebuffer device emulation.
552cf9911fSPeter Grehan  * BAR0 points to the current mode information.
562cf9911fSPeter Grehan  * BAR1 is the 32-bit framebuffer address.
572cf9911fSPeter Grehan  *
5860bfcbd6SGleb Smirnoff  *  -s <b>,fbuf,wait,vga=on|io|off,rfb=<ip>:port,w=width,h=height
592cf9911fSPeter Grehan  */
602cf9911fSPeter Grehan 
612cf9911fSPeter Grehan static int fbuf_debug = 1;
622cf9911fSPeter Grehan #define	DEBUG_INFO	1
632cf9911fSPeter Grehan #define	DEBUG_VERBOSE	4
642cf9911fSPeter Grehan #define	DPRINTF(level, params)  if (level <= fbuf_debug) printf params
652cf9911fSPeter Grehan 
662cf9911fSPeter Grehan 
672cf9911fSPeter Grehan #define	KB	(1024UL)
682cf9911fSPeter Grehan #define	MB	(1024 * 1024UL)
692cf9911fSPeter Grehan 
702cf9911fSPeter Grehan #define	DMEMSZ	128
712cf9911fSPeter Grehan 
722cf9911fSPeter Grehan #define	FB_SIZE		(16*MB)
732cf9911fSPeter Grehan 
742cf9911fSPeter Grehan #define COLS_MAX	1920
752cf9911fSPeter Grehan #define	ROWS_MAX	1200
762cf9911fSPeter Grehan 
772cf9911fSPeter Grehan #define COLS_DEFAULT	1024
782cf9911fSPeter Grehan #define ROWS_DEFAULT	768
792cf9911fSPeter Grehan 
802cf9911fSPeter Grehan #define COLS_MIN	640
812cf9911fSPeter Grehan #define ROWS_MIN	480
822cf9911fSPeter Grehan 
832cf9911fSPeter Grehan struct pci_fbuf_softc {
842cf9911fSPeter Grehan 	struct pci_devinst *fsc_pi;
852cf9911fSPeter Grehan 	struct {
862cf9911fSPeter Grehan 		uint32_t fbsize;
872cf9911fSPeter Grehan 		uint16_t width;
882cf9911fSPeter Grehan 		uint16_t height;
892cf9911fSPeter Grehan 		uint16_t depth;
902cf9911fSPeter Grehan 		uint16_t refreshrate;
912cf9911fSPeter Grehan 		uint8_t  reserved[116];
922cf9911fSPeter Grehan 	} __packed memregs;
932cf9911fSPeter Grehan 
942cf9911fSPeter Grehan 	/* rfb server */
952cf9911fSPeter Grehan 	char      *rfb_host;
96*f4d34383SMarcelo Araujo 	char      *rfb_password;
972cf9911fSPeter Grehan 	int       rfb_port;
982cf9911fSPeter Grehan 	int       rfb_wait;
995a347e3bSPeter Grehan 	int       vga_enabled;
1005a347e3bSPeter Grehan 	int	  vga_full;
1012cf9911fSPeter Grehan 
1022cf9911fSPeter Grehan 	uint32_t  fbaddr;
1032cf9911fSPeter Grehan 	char      *fb_base;
1042cf9911fSPeter Grehan 	uint16_t  gc_width;
1052cf9911fSPeter Grehan 	uint16_t  gc_height;
1062cf9911fSPeter Grehan 	void      *vgasc;
1072cf9911fSPeter Grehan 	struct bhyvegc_image *gc_image;
1082cf9911fSPeter Grehan };
1092cf9911fSPeter Grehan 
1102cf9911fSPeter Grehan static struct pci_fbuf_softc *fbuf_sc;
1112cf9911fSPeter Grehan 
1122cf9911fSPeter Grehan #define	PCI_FBUF_MSI_MSGS	 4
1132cf9911fSPeter Grehan 
1142cf9911fSPeter Grehan static void
1152cf9911fSPeter Grehan pci_fbuf_usage(char *opt)
1162cf9911fSPeter Grehan {
1172cf9911fSPeter Grehan 
1182cf9911fSPeter Grehan 	fprintf(stderr, "Invalid fbuf emulation \"%s\"\r\n", opt);
1195a347e3bSPeter Grehan 	fprintf(stderr, "fbuf: {wait,}{vga=on|io|off,}rfb=<ip>:port\r\n");
1202cf9911fSPeter Grehan }
1212cf9911fSPeter Grehan 
1222cf9911fSPeter Grehan static void
1232cf9911fSPeter Grehan pci_fbuf_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
1242cf9911fSPeter Grehan 	       int baridx, uint64_t offset, int size, uint64_t value)
1252cf9911fSPeter Grehan {
1262cf9911fSPeter Grehan 	struct pci_fbuf_softc *sc;
1272cf9911fSPeter Grehan 	uint8_t *p;
1282cf9911fSPeter Grehan 
1292cf9911fSPeter Grehan 	assert(baridx == 0);
1302cf9911fSPeter Grehan 
1312cf9911fSPeter Grehan 	sc = pi->pi_arg;
1322cf9911fSPeter Grehan 
1332cf9911fSPeter Grehan 	DPRINTF(DEBUG_VERBOSE,
1342cf9911fSPeter Grehan 	    ("fbuf wr: offset 0x%lx, size: %d, value: 0x%lx\n",
1352cf9911fSPeter Grehan 	    offset, size, value));
1362cf9911fSPeter Grehan 
1372cf9911fSPeter Grehan 	if (offset + size > DMEMSZ) {
1382cf9911fSPeter Grehan 		printf("fbuf: write too large, offset %ld size %d\n",
1392cf9911fSPeter Grehan 		       offset, size);
1402cf9911fSPeter Grehan 		return;
1412cf9911fSPeter Grehan 	}
1422cf9911fSPeter Grehan 
1432cf9911fSPeter Grehan 	p = (uint8_t *)&sc->memregs + offset;
1442cf9911fSPeter Grehan 
1452cf9911fSPeter Grehan 	switch (size) {
1462cf9911fSPeter Grehan 	case 1:
1472cf9911fSPeter Grehan 		*p = value;
1482cf9911fSPeter Grehan 		break;
1492cf9911fSPeter Grehan 	case 2:
1502cf9911fSPeter Grehan 		*(uint16_t *)p = value;
1512cf9911fSPeter Grehan 		break;
1522cf9911fSPeter Grehan 	case 4:
1532cf9911fSPeter Grehan 		*(uint32_t *)p = value;
1542cf9911fSPeter Grehan 		break;
1552cf9911fSPeter Grehan 	case 8:
1562cf9911fSPeter Grehan 		*(uint64_t *)p = value;
1572cf9911fSPeter Grehan 		break;
1582cf9911fSPeter Grehan 	default:
1592cf9911fSPeter Grehan 		printf("fbuf: write unknown size %d\n", size);
1602cf9911fSPeter Grehan 		break;
1612cf9911fSPeter Grehan 	}
1622cf9911fSPeter Grehan 
1632cf9911fSPeter Grehan 	if (!sc->gc_image->vgamode && sc->memregs.width == 0 &&
1642cf9911fSPeter Grehan 	    sc->memregs.height == 0) {
1652cf9911fSPeter Grehan 		DPRINTF(DEBUG_INFO, ("switching to VGA mode\r\n"));
1662cf9911fSPeter Grehan 		sc->gc_image->vgamode = 1;
1672cf9911fSPeter Grehan 		sc->gc_width = 0;
1682cf9911fSPeter Grehan 		sc->gc_height = 0;
1692cf9911fSPeter Grehan 	} else if (sc->gc_image->vgamode && sc->memregs.width != 0 &&
1702cf9911fSPeter Grehan 	    sc->memregs.height != 0) {
1712cf9911fSPeter Grehan 		DPRINTF(DEBUG_INFO, ("switching to VESA mode\r\n"));
1722cf9911fSPeter Grehan 		sc->gc_image->vgamode = 0;
1732cf9911fSPeter Grehan 	}
1742cf9911fSPeter Grehan }
1752cf9911fSPeter Grehan 
1762cf9911fSPeter Grehan uint64_t
1772cf9911fSPeter Grehan pci_fbuf_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
1782cf9911fSPeter Grehan 	      int baridx, uint64_t offset, int size)
1792cf9911fSPeter Grehan {
1802cf9911fSPeter Grehan 	struct pci_fbuf_softc *sc;
1812cf9911fSPeter Grehan 	uint8_t *p;
1822cf9911fSPeter Grehan 	uint64_t value;
1832cf9911fSPeter Grehan 
1842cf9911fSPeter Grehan 	assert(baridx == 0);
1852cf9911fSPeter Grehan 
1862cf9911fSPeter Grehan 	sc = pi->pi_arg;
1872cf9911fSPeter Grehan 
1882cf9911fSPeter Grehan 
1892cf9911fSPeter Grehan 	if (offset + size > DMEMSZ) {
1902cf9911fSPeter Grehan 		printf("fbuf: read too large, offset %ld size %d\n",
1912cf9911fSPeter Grehan 		       offset, size);
1922cf9911fSPeter Grehan 		return (0);
1932cf9911fSPeter Grehan 	}
1942cf9911fSPeter Grehan 
1952cf9911fSPeter Grehan 	p = (uint8_t *)&sc->memregs + offset;
1962cf9911fSPeter Grehan 	value = 0;
1972cf9911fSPeter Grehan 	switch (size) {
1982cf9911fSPeter Grehan 	case 1:
1992cf9911fSPeter Grehan 		value = *p;
2002cf9911fSPeter Grehan 		break;
2012cf9911fSPeter Grehan 	case 2:
2022cf9911fSPeter Grehan 		value = *(uint16_t *)p;
2032cf9911fSPeter Grehan 		break;
2042cf9911fSPeter Grehan 	case 4:
2052cf9911fSPeter Grehan 		value = *(uint32_t *)p;
2062cf9911fSPeter Grehan 		break;
2072cf9911fSPeter Grehan 	case 8:
2082cf9911fSPeter Grehan 		value = *(uint64_t *)p;
2092cf9911fSPeter Grehan 		break;
2102cf9911fSPeter Grehan 	default:
2112cf9911fSPeter Grehan 		printf("fbuf: read unknown size %d\n", size);
2122cf9911fSPeter Grehan 		break;
2132cf9911fSPeter Grehan 	}
2142cf9911fSPeter Grehan 
2152cf9911fSPeter Grehan 	DPRINTF(DEBUG_VERBOSE,
2162cf9911fSPeter Grehan 	    ("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx\n",
2172cf9911fSPeter Grehan 	     offset, size, value));
2182cf9911fSPeter Grehan 
2192cf9911fSPeter Grehan 	return (value);
2202cf9911fSPeter Grehan }
2212cf9911fSPeter Grehan 
2222cf9911fSPeter Grehan static int
2232cf9911fSPeter Grehan pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts)
2242cf9911fSPeter Grehan {
2252cf9911fSPeter Grehan 	char	*uopts, *xopts, *config;
2262cf9911fSPeter Grehan 	char	*tmpstr;
2272cf9911fSPeter Grehan 	int	ret;
2282cf9911fSPeter Grehan 
2292cf9911fSPeter Grehan 	ret = 0;
2302cf9911fSPeter Grehan 	uopts = strdup(opts);
2312cf9911fSPeter Grehan 	for (xopts = strtok(uopts, ",");
2322cf9911fSPeter Grehan 	     xopts != NULL;
2332cf9911fSPeter Grehan 	     xopts = strtok(NULL, ",")) {
2342cf9911fSPeter Grehan 		if (strcmp(xopts, "wait") == 0) {
2352cf9911fSPeter Grehan 			sc->rfb_wait = 1;
2362cf9911fSPeter Grehan 			continue;
2372cf9911fSPeter Grehan 		}
2382cf9911fSPeter Grehan 
2392cf9911fSPeter Grehan 		if ((config = strchr(xopts, '=')) == NULL) {
2402cf9911fSPeter Grehan 			pci_fbuf_usage(xopts);
2412cf9911fSPeter Grehan 			ret = -1;
2422cf9911fSPeter Grehan 			goto done;
2432cf9911fSPeter Grehan 		}
2442cf9911fSPeter Grehan 
2452cf9911fSPeter Grehan 		*config++ = '\0';
2462cf9911fSPeter Grehan 
2472cf9911fSPeter Grehan 		DPRINTF(DEBUG_VERBOSE, ("pci_fbuf option %s = %s\r\n",
2482cf9911fSPeter Grehan 		   xopts, config));
2492cf9911fSPeter Grehan 
2505a347e3bSPeter Grehan 		if (!strcmp(xopts, "tcp") || !strcmp(xopts, "rfb")) {
2512cf9911fSPeter Grehan 			/* parse host-ip:port */
2522cf9911fSPeter Grehan 		        tmpstr = strsep(&config, ":");
2532cf9911fSPeter Grehan 			if (!config)
2542cf9911fSPeter Grehan 				sc->rfb_port = atoi(tmpstr);
2552cf9911fSPeter Grehan 			else {
2562cf9911fSPeter Grehan 				sc->rfb_port = atoi(config);
2572cf9911fSPeter Grehan 				sc->rfb_host = tmpstr;
2582cf9911fSPeter Grehan 			}
2595a347e3bSPeter Grehan 	        } else if (!strcmp(xopts, "vga")) {
2605a347e3bSPeter Grehan 			if (!strcmp(config, "off")) {
2615a347e3bSPeter Grehan 				sc->vga_enabled = 0;
2625a347e3bSPeter Grehan 			} else if (!strcmp(config, "io")) {
2635a347e3bSPeter Grehan 				sc->vga_enabled = 1;
2645a347e3bSPeter Grehan 				sc->vga_full = 0;
2655a347e3bSPeter Grehan 			} else if (!strcmp(config, "on")) {
2665a347e3bSPeter Grehan 				sc->vga_enabled = 1;
2675a347e3bSPeter Grehan 				sc->vga_full = 1;
2685a347e3bSPeter Grehan 			} else {
2695a347e3bSPeter Grehan 				pci_fbuf_usage(opts);
2705a347e3bSPeter Grehan 				ret = -1;
2715a347e3bSPeter Grehan 				goto done;
2725a347e3bSPeter Grehan 			}
2732cf9911fSPeter Grehan 	        } else if (!strcmp(xopts, "w")) {
2742cf9911fSPeter Grehan 		        sc->memregs.width = atoi(config);
2752cf9911fSPeter Grehan 			if (sc->memregs.width > COLS_MAX) {
2762cf9911fSPeter Grehan 				pci_fbuf_usage(xopts);
2772cf9911fSPeter Grehan 				ret = -1;
2782cf9911fSPeter Grehan 				goto done;
2792cf9911fSPeter Grehan 			} else if (sc->memregs.width == 0)
2802cf9911fSPeter Grehan 				sc->memregs.width = 1920;
2812cf9911fSPeter Grehan 		} else if (!strcmp(xopts, "h")) {
2822cf9911fSPeter Grehan 			sc->memregs.height = atoi(config);
2832cf9911fSPeter Grehan 			if (sc->memregs.height > ROWS_MAX) {
2842cf9911fSPeter Grehan 				pci_fbuf_usage(xopts);
2852cf9911fSPeter Grehan 				ret = -1;
2862cf9911fSPeter Grehan 				goto done;
2872cf9911fSPeter Grehan 			} else if (sc->memregs.height == 0)
2882cf9911fSPeter Grehan 				sc->memregs.height = 1080;
289*f4d34383SMarcelo Araujo 		} else if (!strcmp(xopts, "password")) {
290*f4d34383SMarcelo Araujo 			sc->rfb_password = config;
2912cf9911fSPeter Grehan 		} else {
2922cf9911fSPeter Grehan 			pci_fbuf_usage(xopts);
2932cf9911fSPeter Grehan 			ret = -1;
2942cf9911fSPeter Grehan 			goto done;
2952cf9911fSPeter Grehan 		}
2962cf9911fSPeter Grehan 	}
2972cf9911fSPeter Grehan 
2982cf9911fSPeter Grehan done:
2992cf9911fSPeter Grehan 	return (ret);
3002cf9911fSPeter Grehan }
3012cf9911fSPeter Grehan 
3022cf9911fSPeter Grehan 
3032cf9911fSPeter Grehan extern void vga_render(struct bhyvegc *gc, void *arg);
3042cf9911fSPeter Grehan 
3052cf9911fSPeter Grehan void
3062cf9911fSPeter Grehan pci_fbuf_render(struct bhyvegc *gc, void *arg)
3072cf9911fSPeter Grehan {
3082cf9911fSPeter Grehan 	struct pci_fbuf_softc *sc;
3092cf9911fSPeter Grehan 
3102cf9911fSPeter Grehan 	sc = arg;
3112cf9911fSPeter Grehan 
3125a347e3bSPeter Grehan 	if (sc->vga_full && sc->gc_image->vgamode) {
3132cf9911fSPeter Grehan 		/* TODO: mode switching to vga and vesa should use the special
3142cf9911fSPeter Grehan 		 *      EFI-bhyve protocol port.
3152cf9911fSPeter Grehan 		 */
3162cf9911fSPeter Grehan 		vga_render(gc, sc->vgasc);
3172cf9911fSPeter Grehan 		return;
3182cf9911fSPeter Grehan 	}
3192cf9911fSPeter Grehan 	if (sc->gc_width != sc->memregs.width ||
3202cf9911fSPeter Grehan 	    sc->gc_height != sc->memregs.height) {
3212cf9911fSPeter Grehan 		bhyvegc_resize(gc, sc->memregs.width, sc->memregs.height);
3222cf9911fSPeter Grehan 		sc->gc_width = sc->memregs.width;
3232cf9911fSPeter Grehan 		sc->gc_height = sc->memregs.height;
3242cf9911fSPeter Grehan 	}
3252cf9911fSPeter Grehan 
3262cf9911fSPeter Grehan 	return;
3272cf9911fSPeter Grehan }
3282cf9911fSPeter Grehan 
3292cf9911fSPeter Grehan static int
3302cf9911fSPeter Grehan pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
3312cf9911fSPeter Grehan {
3322cf9911fSPeter Grehan 	int error, prot;
3332cf9911fSPeter Grehan 	struct pci_fbuf_softc *sc;
3342cf9911fSPeter Grehan 
3352cf9911fSPeter Grehan 	if (fbuf_sc != NULL) {
3362cf9911fSPeter Grehan 		fprintf(stderr, "Only one frame buffer device is allowed.\n");
3372cf9911fSPeter Grehan 		return (-1);
3382cf9911fSPeter Grehan 	}
3392cf9911fSPeter Grehan 
3402cf9911fSPeter Grehan 	sc = calloc(1, sizeof(struct pci_fbuf_softc));
3412cf9911fSPeter Grehan 
3422cf9911fSPeter Grehan 	pi->pi_arg = sc;
3432cf9911fSPeter Grehan 
3442cf9911fSPeter Grehan 	/* initialize config space */
3452cf9911fSPeter Grehan 	pci_set_cfgdata16(pi, PCIR_DEVICE, 0x40FB);
3462cf9911fSPeter Grehan 	pci_set_cfgdata16(pi, PCIR_VENDOR, 0xFB5D);
3472cf9911fSPeter Grehan 	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_DISPLAY);
3482cf9911fSPeter Grehan 	pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_DISPLAY_VGA);
3492cf9911fSPeter Grehan 
3502cf9911fSPeter Grehan 	error = pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, DMEMSZ);
3512cf9911fSPeter Grehan 	assert(error == 0);
3522cf9911fSPeter Grehan 
3532cf9911fSPeter Grehan 	error = pci_emul_alloc_bar(pi, 1, PCIBAR_MEM32, FB_SIZE);
3542cf9911fSPeter Grehan 	assert(error == 0);
3552cf9911fSPeter Grehan 
3562cf9911fSPeter Grehan 	error = pci_emul_add_msicap(pi, PCI_FBUF_MSI_MSGS);
3572cf9911fSPeter Grehan 	assert(error == 0);
3582cf9911fSPeter Grehan 
3592cf9911fSPeter Grehan 	sc->fbaddr = pi->pi_bar[1].addr;
3602cf9911fSPeter Grehan 	sc->memregs.fbsize = FB_SIZE;
3612cf9911fSPeter Grehan 	sc->memregs.width  = COLS_DEFAULT;
3622cf9911fSPeter Grehan 	sc->memregs.height = ROWS_DEFAULT;
3632cf9911fSPeter Grehan 	sc->memregs.depth  = 32;
3642cf9911fSPeter Grehan 
3655a347e3bSPeter Grehan 	sc->vga_enabled = 1;
3665a347e3bSPeter Grehan 	sc->vga_full = 0;
3675a347e3bSPeter Grehan 
3682cf9911fSPeter Grehan 	sc->fsc_pi = pi;
3692cf9911fSPeter Grehan 
3702cf9911fSPeter Grehan 	error = pci_fbuf_parse_opts(sc, opts);
3712cf9911fSPeter Grehan 	if (error != 0)
3722cf9911fSPeter Grehan 		goto done;
3732cf9911fSPeter Grehan 
3745a347e3bSPeter Grehan 	/* XXX until VGA rendering is enabled */
3755a347e3bSPeter Grehan 	if (sc->vga_full != 0) {
3765a347e3bSPeter Grehan 		fprintf(stderr, "pci_fbuf: VGA rendering not enabled");
3775a347e3bSPeter Grehan 		goto done;
3785a347e3bSPeter Grehan 	}
3795a347e3bSPeter Grehan 
3802cf9911fSPeter Grehan 	sc->fb_base = vm_create_devmem(ctx, VM_FRAMEBUFFER, "framebuffer", FB_SIZE);
3812cf9911fSPeter Grehan 	if (sc->fb_base == MAP_FAILED) {
3822cf9911fSPeter Grehan 		error = -1;
3832cf9911fSPeter Grehan 		goto done;
3842cf9911fSPeter Grehan 	}
3852cf9911fSPeter Grehan 	DPRINTF(DEBUG_INFO, ("fbuf frame buffer base: %p [sz %lu]\r\n",
3862cf9911fSPeter Grehan 	        sc->fb_base, FB_SIZE));
3872cf9911fSPeter Grehan 
3882cf9911fSPeter Grehan 	/*
3892cf9911fSPeter Grehan 	 * Map the framebuffer into the guest address space.
3902cf9911fSPeter Grehan 	 * XXX This may fail if the BAR is different than a prior
3912cf9911fSPeter Grehan 	 * run. In this case flag the error. This will be fixed
3922cf9911fSPeter Grehan 	 * when a change_memseg api is available.
3932cf9911fSPeter Grehan 	 */
3942cf9911fSPeter Grehan 	prot = PROT_READ | PROT_WRITE;
3952cf9911fSPeter Grehan 	if (vm_mmap_memseg(ctx, sc->fbaddr, VM_FRAMEBUFFER, 0, FB_SIZE, prot) != 0) {
3962cf9911fSPeter Grehan 		fprintf(stderr, "pci_fbuf: mapseg failed - try deleting VM and restarting\n");
3972cf9911fSPeter Grehan 		error = -1;
3982cf9911fSPeter Grehan 		goto done;
3992cf9911fSPeter Grehan 	}
4002cf9911fSPeter Grehan 
4012cf9911fSPeter Grehan 	console_init(sc->memregs.width, sc->memregs.height, sc->fb_base);
4022cf9911fSPeter Grehan 	console_fb_register(pci_fbuf_render, sc);
4032cf9911fSPeter Grehan 
4045a347e3bSPeter Grehan 	if (sc->vga_enabled)
4055a347e3bSPeter Grehan 		sc->vgasc = vga_init(!sc->vga_full);
4062cf9911fSPeter Grehan 	sc->gc_image = console_get_image();
4072cf9911fSPeter Grehan 
4082cf9911fSPeter Grehan 	fbuf_sc = sc;
4092cf9911fSPeter Grehan 
4102cf9911fSPeter Grehan 	memset((void *)sc->fb_base, 0, FB_SIZE);
4112cf9911fSPeter Grehan 
412*f4d34383SMarcelo Araujo 	error = rfb_init(sc->rfb_host, sc->rfb_port, sc->rfb_wait, sc->rfb_password);
4132cf9911fSPeter Grehan done:
4142cf9911fSPeter Grehan 	if (error)
4152cf9911fSPeter Grehan 		free(sc);
4162cf9911fSPeter Grehan 
4172cf9911fSPeter Grehan 	return (error);
4182cf9911fSPeter Grehan }
4192cf9911fSPeter Grehan 
4202cf9911fSPeter Grehan struct pci_devemu pci_fbuf = {
4212cf9911fSPeter Grehan 	.pe_emu =	"fbuf",
4222cf9911fSPeter Grehan 	.pe_init =	pci_fbuf_init,
4232cf9911fSPeter Grehan 	.pe_barwrite =	pci_fbuf_write,
4242cf9911fSPeter Grehan 	.pe_barread =	pci_fbuf_read
4252cf9911fSPeter Grehan };
4262cf9911fSPeter Grehan PCI_EMUL_SET(pci_fbuf);
427