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