Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_fbuf.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | ||||||||||||
#include <stdlib.h> | #include <stdlib.h> | |||||||||||
#include <string.h> | #include <string.h> | |||||||||||
#include <errno.h> | #include <errno.h> | |||||||||||
#include <unistd.h> | #include <unistd.h> | |||||||||||
#include "bhyvegc.h" | #include "bhyvegc.h" | |||||||||||
#include "bhyverun.h" | #include "bhyverun.h" | |||||||||||
#include "config.h" | ||||||||||||
#include "debug.h" | #include "debug.h" | |||||||||||
#include "console.h" | #include "console.h" | |||||||||||
#include "inout.h" | #include "inout.h" | |||||||||||
#include "pci_emul.h" | #include "pci_emul.h" | |||||||||||
#include "rfb.h" | #include "rfb.h" | |||||||||||
#include "vga.h" | #include "vga.h" | |||||||||||
/* | /* | |||||||||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | struct pci_fbuf_softc { | |||||||||||
struct bhyvegc_image *gc_image; | struct bhyvegc_image *gc_image; | |||||||||||
}; | }; | |||||||||||
static struct pci_fbuf_softc *fbuf_sc; | static struct pci_fbuf_softc *fbuf_sc; | |||||||||||
#define PCI_FBUF_MSI_MSGS 4 | #define PCI_FBUF_MSI_MSGS 4 | |||||||||||
static void | static void | |||||||||||
pci_fbuf_usage(char *opt) | ||||||||||||
{ | ||||||||||||
EPRINTLN("Invalid fbuf emulation option \"%s\"", opt); | ||||||||||||
EPRINTLN("fbuf: {wait,}{vga=on|io|off,}rfb=<ip>:port" | ||||||||||||
"{,w=width}{,h=height}"); | ||||||||||||
} | ||||||||||||
static void | ||||||||||||
pci_fbuf_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | pci_fbuf_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | |||||||||||
int baridx, uint64_t offset, int size, uint64_t value) | int baridx, uint64_t offset, int size, uint64_t value) | |||||||||||
{ | { | |||||||||||
struct pci_fbuf_softc *sc; | struct pci_fbuf_softc *sc; | |||||||||||
uint8_t *p; | uint8_t *p; | |||||||||||
assert(baridx == 0); | assert(baridx == 0); | |||||||||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | pci_fbuf_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | |||||||||||
DPRINTF(DEBUG_VERBOSE, | DPRINTF(DEBUG_VERBOSE, | |||||||||||
("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx", | ("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx", | |||||||||||
offset, size, value)); | offset, size, value)); | |||||||||||
return (value); | return (value); | |||||||||||
} | } | |||||||||||
static int | static int | |||||||||||
pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts) | pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) | |||||||||||
{ | { | |||||||||||
char *uopts, *uoptsbak, *xopts, *config; | const char *value; | |||||||||||
char *tmpstr; | char *cp; | |||||||||||
int ret; | ||||||||||||
ret = 0; | sc->rfb_wait = get_config_bool_node_default(nvl, "wait", false); | |||||||||||
uoptsbak = uopts = strdup(opts); | ||||||||||||
while ((xopts = strsep(&uopts, ",")) != NULL) { | ||||||||||||
if (strcmp(xopts, "wait") == 0) { | ||||||||||||
sc->rfb_wait = 1; | ||||||||||||
continue; | ||||||||||||
} | ||||||||||||
if ((config = strchr(xopts, '=')) == NULL) { | /* Prefer "rfb" to "tcp". */ | |||||||||||
pci_fbuf_usage(xopts); | value = get_config_value_node(nvl, "rfb"); | |||||||||||
ret = -1; | if (value == NULL) | |||||||||||
goto done; | value = get_config_value_node(nvl, "tcp"); | |||||||||||
} | if (value != NULL) { | |||||||||||
*config++ = '\0'; | ||||||||||||
DPRINTF(DEBUG_VERBOSE, ("pci_fbuf option %s = %s", | ||||||||||||
xopts, config)); | ||||||||||||
if (!strcmp(xopts, "tcp") || !strcmp(xopts, "rfb")) { | ||||||||||||
/* | /* | |||||||||||
* IPv4 -- host-ip:port | * IPv4 -- host-ip:port | |||||||||||
* IPv6 -- [host-ip%zone]:port | * IPv6 -- [host-ip%zone]:port | |||||||||||
* XXX for now port is mandatory. | * XXX for now port is mandatory for IPv4. | |||||||||||
*/ | */ | |||||||||||
tmpstr = strsep(&config, "]"); | if (value[0] == '[') { | |||||||||||
if (config) { | cp = strchr(value + 1, ']'); | |||||||||||
if (tmpstr[0] == '[') | if (cp == NULL || cp == value + 1) { | |||||||||||
tmpstr++; | EPRINTLN("fbuf: Invalid IPv6 address: \"%s\"", | |||||||||||
sc->rfb_host = strdup(tmpstr); | value); | |||||||||||
if (config[0] == ':') | return (-1); | |||||||||||
config++; | ||||||||||||
else { | ||||||||||||
pci_fbuf_usage(xopts); | ||||||||||||
ret = -1; | ||||||||||||
goto done; | ||||||||||||
} | } | |||||||||||
sc->rfb_port = atoi(config); | sc->rfb_host = strndup(value + 1, cp - (value + 1)); | |||||||||||
cp++; | ||||||||||||
if (*cp == ':') { | ||||||||||||
cp++; | ||||||||||||
if (*cp == '\0') { | ||||||||||||
EPRINTLN( | ||||||||||||
"fbuf: Missing port number: \"%s\"", | ||||||||||||
value); | ||||||||||||
return (-1); | ||||||||||||
} | ||||||||||||
sc->rfb_port = atoi(cp); | ||||||||||||
wanpengqian_gmail.com: Already plus one in line 249. | ||||||||||||
} else if (*cp != '\0') { | ||||||||||||
EPRINTLN("fbuf: Invalid IPv6 address: \"%s\"", | ||||||||||||
value); | ||||||||||||
return (-1); | ||||||||||||
} | ||||||||||||
} else { | } else { | |||||||||||
config = tmpstr; | cp = strchr(value, ':'); | |||||||||||
tmpstr = strsep(&config, ":"); | if (cp == NULL) { | |||||||||||
if (!config) | sc->rfb_port = atoi(value); | |||||||||||
sc->rfb_port = atoi(tmpstr); | } else { | |||||||||||
else { | sc->rfb_host = strndup(value, cp - value); | |||||||||||
sc->rfb_port = atoi(config); | cp++; | |||||||||||
sc->rfb_host = strdup(tmpstr); | if (*cp == '\0') { | |||||||||||
EPRINTLN( | ||||||||||||
"fbuf: Missing port number: \"%s\"", | ||||||||||||
value); | ||||||||||||
return (-1); | ||||||||||||
} | } | |||||||||||
sc->rfb_port = atoi(cp); | ||||||||||||
Done Inline Actions
Already plus one in line 268. wanpengqian_gmail.com: Already plus one in line 268. | ||||||||||||
} | } | |||||||||||
} else if (!strcmp(xopts, "vga")) { | } | |||||||||||
if (!strcmp(config, "off")) { | } | |||||||||||
value = get_config_value_node(nvl, "vga"); | ||||||||||||
if (value != NULL) { | ||||||||||||
if (strcmp(value, "off") == 0) { | ||||||||||||
sc->vga_enabled = 0; | sc->vga_enabled = 0; | |||||||||||
} else if (!strcmp(config, "io")) { | } else if (strcmp(value, "io") == 0) { | |||||||||||
sc->vga_enabled = 1; | sc->vga_enabled = 1; | |||||||||||
sc->vga_full = 0; | sc->vga_full = 0; | |||||||||||
} else if (!strcmp(config, "on")) { | } else if (strcmp(value, "on") == 0) { | |||||||||||
sc->vga_enabled = 1; | sc->vga_enabled = 1; | |||||||||||
sc->vga_full = 1; | sc->vga_full = 1; | |||||||||||
} else { | } else { | |||||||||||
pci_fbuf_usage(xopts); | EPRINTLN("fbuf: Invalid vga setting: \"%s\"", value); | |||||||||||
ret = -1; | return (-1); | |||||||||||
goto done; | ||||||||||||
} | } | |||||||||||
} else if (!strcmp(xopts, "w")) { | } | |||||||||||
sc->memregs.width = atoi(config); | ||||||||||||
value = get_config_value_node(nvl, "w"); | ||||||||||||
if (value != NULL) { | ||||||||||||
sc->memregs.width = atoi(value); | ||||||||||||
if (sc->memregs.width > COLS_MAX) { | if (sc->memregs.width > COLS_MAX) { | |||||||||||
pci_fbuf_usage(xopts); | EPRINTLN("fbuf: width %d too large", sc->memregs.width); | |||||||||||
ret = -1; | return (-1); | |||||||||||
goto done; | } | |||||||||||
} else if (sc->memregs.width == 0) | if (sc->memregs.width == 0) | |||||||||||
sc->memregs.width = 1920; | sc->memregs.width = 1920; | |||||||||||
} else if (!strcmp(xopts, "h")) { | } | |||||||||||
sc->memregs.height = atoi(config); | ||||||||||||
value = get_config_value_node(nvl, "h"); | ||||||||||||
if (value != NULL) { | ||||||||||||
sc->memregs.height = atoi(value); | ||||||||||||
if (sc->memregs.height > ROWS_MAX) { | if (sc->memregs.height > ROWS_MAX) { | |||||||||||
pci_fbuf_usage(xopts); | EPRINTLN("fbuf: height %d too large", | |||||||||||
ret = -1; | sc->memregs.height); | |||||||||||
goto done; | return (-1); | |||||||||||
} else if (sc->memregs.height == 0) | } | |||||||||||
if (sc->memregs.height == 0) | ||||||||||||
sc->memregs.height = 1080; | sc->memregs.height = 1080; | |||||||||||
} else if (!strcmp(xopts, "password")) { | ||||||||||||
sc->rfb_password = strdup(config); | ||||||||||||
} else { | ||||||||||||
pci_fbuf_usage(xopts); | ||||||||||||
ret = -1; | ||||||||||||
goto done; | ||||||||||||
} | } | |||||||||||
} | ||||||||||||
done: | value = get_config_value_node(nvl, "password"); | |||||||||||
free(uoptsbak); | if (value != NULL) | |||||||||||
return (ret); | sc->rfb_password = strdup(value); | |||||||||||
return (0); | ||||||||||||
} | } | |||||||||||
extern void vga_render(struct bhyvegc *gc, void *arg); | extern void vga_render(struct bhyvegc *gc, void *arg); | |||||||||||
void | void | |||||||||||
pci_fbuf_render(struct bhyvegc *gc, void *arg) | pci_fbuf_render(struct bhyvegc *gc, void *arg) | |||||||||||
{ | { | |||||||||||
Show All 14 Lines | if (sc->gc_width != sc->memregs.width || | |||||||||||
sc->gc_width = sc->memregs.width; | sc->gc_width = sc->memregs.width; | |||||||||||
sc->gc_height = sc->memregs.height; | sc->gc_height = sc->memregs.height; | |||||||||||
} | } | |||||||||||
return; | return; | |||||||||||
} | } | |||||||||||
static int | static int | |||||||||||
pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | |||||||||||
{ | { | |||||||||||
int error, prot; | int error, prot; | |||||||||||
struct pci_fbuf_softc *sc; | struct pci_fbuf_softc *sc; | |||||||||||
if (fbuf_sc != NULL) { | if (fbuf_sc != NULL) { | |||||||||||
EPRINTLN("Only one frame buffer device is allowed."); | EPRINTLN("Only one frame buffer device is allowed."); | |||||||||||
return (-1); | return (-1); | |||||||||||
} | } | |||||||||||
Show All 23 Lines | pci_fbuf_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | |||||||||||
sc->memregs.height = ROWS_DEFAULT; | sc->memregs.height = ROWS_DEFAULT; | |||||||||||
sc->memregs.depth = 32; | sc->memregs.depth = 32; | |||||||||||
sc->vga_enabled = 1; | sc->vga_enabled = 1; | |||||||||||
sc->vga_full = 0; | sc->vga_full = 0; | |||||||||||
sc->fsc_pi = pi; | sc->fsc_pi = pi; | |||||||||||
error = pci_fbuf_parse_opts(sc, opts); | error = pci_fbuf_parse_config(sc, nvl); | |||||||||||
if (error != 0) | if (error != 0) | |||||||||||
goto done; | goto done; | |||||||||||
/* XXX until VGA rendering is enabled */ | /* XXX until VGA rendering is enabled */ | |||||||||||
if (sc->vga_full != 0) { | if (sc->vga_full != 0) { | |||||||||||
EPRINTLN("pci_fbuf: VGA rendering not enabled"); | EPRINTLN("pci_fbuf: VGA rendering not enabled"); | |||||||||||
goto done; | goto done; | |||||||||||
} | } | |||||||||||
▲ Show 20 Lines • Show All 64 Lines • Show Last 20 Lines |
Already plus one in line 249.