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.