Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_lpc.c
Show All 39 Lines | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <vmmapi.h> | #include <vmmapi.h> | ||||
#include "acpi.h" | #include "acpi.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "bootrom.h" | #include "bootrom.h" | ||||
#include "config.h" | |||||
#include "inout.h" | #include "inout.h" | ||||
#include "pci_emul.h" | #include "pci_emul.h" | ||||
#include "pci_irq.h" | #include "pci_irq.h" | ||||
#include "pci_lpc.h" | #include "pci_lpc.h" | ||||
#include "pctestdev.h" | #include "pctestdev.h" | ||||
#include "uart_emul.h" | #include "uart_emul.h" | ||||
#define IO_ICU1 0x20 | #define IO_ICU1 0x20 | ||||
#define IO_ICU2 0xA0 | #define IO_ICU2 0xA0 | ||||
SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); | SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); | ||||
SET_DECLARE(lpc_sysres_set, struct lpc_sysres); | SET_DECLARE(lpc_sysres_set, struct lpc_sysres); | ||||
#define ELCR_PORT 0x4d0 | #define ELCR_PORT 0x4d0 | ||||
SYSRES_IO(ELCR_PORT, 2); | SYSRES_IO(ELCR_PORT, 2); | ||||
#define IO_TIMER1_PORT 0x40 | #define IO_TIMER1_PORT 0x40 | ||||
#define NMISC_PORT 0x61 | #define NMISC_PORT 0x61 | ||||
SYSRES_IO(NMISC_PORT, 1); | SYSRES_IO(NMISC_PORT, 1); | ||||
static struct pci_devinst *lpc_bridge; | static struct pci_devinst *lpc_bridge; | ||||
static const char *romfile; | |||||
#define LPC_UART_NUM 4 | #define LPC_UART_NUM 4 | ||||
static struct lpc_uart_softc { | static struct lpc_uart_softc { | ||||
struct uart_softc *uart_softc; | struct uart_softc *uart_softc; | ||||
const char *opts; | |||||
int iobase; | int iobase; | ||||
int irq; | int irq; | ||||
int enabled; | int enabled; | ||||
} lpc_uart_softc[LPC_UART_NUM]; | } lpc_uart_softc[LPC_UART_NUM]; | ||||
static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2", "COM3", "COM4" }; | static const char *lpc_uart_names[LPC_UART_NUM] = { | ||||
"com1", "com2", "com3", "com4" | |||||
}; | |||||
static bool pctestdev_present; | static const char *lpc_uart_acpi_names[LPC_UART_NUM] = { | ||||
"COM1", "COM2", "COM3", "COM4" | |||||
}; | |||||
rew: The following gets printed to terminal on boot:
/tmp/bhyve.lXJmgyl 656: Device… | |||||
Done Inline ActionsI decided to just fix the warning by using uppercase names in the DSDT instead. Thanks for reporting it though, I had missed it. jhb: I decided to just fix the warning by using uppercase names in the DSDT instead. Thanks for… | |||||
/* | /* | ||||
* LPC device configuration is in the following form: | * LPC device configuration is in the following form: | ||||
* <lpc_device_name>[,<options>] | * <lpc_device_name>[,<options>] | ||||
* For e.g. "com1,stdio" or "bootrom,/var/romfile" | * For e.g. "com1,stdio" or "bootrom,/var/romfile" | ||||
*/ | */ | ||||
int | int | ||||
lpc_device_parse(const char *opts) | lpc_device_parse(const char *opts) | ||||
{ | { | ||||
int unit, error; | int unit, error; | ||||
char *str, *cpy, *lpcdev; | char *str, *cpy, *lpcdev, *node_name; | ||||
error = -1; | error = -1; | ||||
str = cpy = strdup(opts); | str = cpy = strdup(opts); | ||||
lpcdev = strsep(&str, ","); | lpcdev = strsep(&str, ","); | ||||
if (lpcdev != NULL) { | if (lpcdev != NULL) { | ||||
if (strcasecmp(lpcdev, "bootrom") == 0) { | if (strcasecmp(lpcdev, "bootrom") == 0) { | ||||
romfile = str; | set_config_value("lpc.bootrom", str); | ||||
error = 0; | error = 0; | ||||
goto done; | goto done; | ||||
} | } | ||||
for (unit = 0; unit < LPC_UART_NUM; unit++) { | for (unit = 0; unit < LPC_UART_NUM; unit++) { | ||||
if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) { | if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) { | ||||
lpc_uart_softc[unit].opts = str; | asprintf(&node_name, "lpc.%s.path", | ||||
lpc_uart_names[unit]); | |||||
set_config_value(node_name, str); | |||||
free(node_name); | |||||
error = 0; | error = 0; | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
if (strcasecmp(lpcdev, pctestdev_getname()) == 0) { | if (strcasecmp(lpcdev, pctestdev_getname()) == 0) { | ||||
if (pctestdev_present) { | asprintf(&node_name, "lpc.%s", pctestdev_getname()); | ||||
EPRINTLN("More than one %s device conf is " | set_config_bool(node_name, true); | ||||
"specified; only one is allowed.", | free(node_name); | ||||
pctestdev_getname()); | |||||
} else if (pctestdev_parse(str) == 0) { | |||||
pctestdev_present = true; | |||||
error = 0; | error = 0; | ||||
free(cpy); | |||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
} | |||||
done: | done: | ||||
if (error) | |||||
free(cpy); | free(cpy); | ||||
return (error); | return (error); | ||||
} | } | ||||
void | void | ||||
lpc_print_supported_devices() | lpc_print_supported_devices() | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
printf("bootrom\n"); | printf("bootrom\n"); | ||||
for (i = 0; i < LPC_UART_NUM; i++) | for (i = 0; i < LPC_UART_NUM; i++) | ||||
printf("%s\n", lpc_uart_names[i]); | printf("%s\n", lpc_uart_names[i]); | ||||
printf("%s\n", pctestdev_getname()); | printf("%s\n", pctestdev_getname()); | ||||
} | } | ||||
const char * | const char * | ||||
lpc_bootrom(void) | lpc_bootrom(void) | ||||
{ | { | ||||
return (romfile); | return (get_config_value("lpc.bootrom")); | ||||
} | } | ||||
static void | static void | ||||
lpc_uart_intr_assert(void *arg) | lpc_uart_intr_assert(void *arg) | ||||
{ | { | ||||
struct lpc_uart_softc *sc = arg; | struct lpc_uart_softc *sc = arg; | ||||
assert(sc->irq >= 0); | assert(sc->irq >= 0); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | lpc_uart_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
lpc_init(struct vmctx *ctx) | lpc_init(struct vmctx *ctx) | ||||
{ | { | ||||
struct lpc_uart_softc *sc; | struct lpc_uart_softc *sc; | ||||
struct inout_port iop; | struct inout_port iop; | ||||
const char *name; | const char *backend, *name, *romfile; | ||||
char *node_name; | |||||
int unit, error; | int unit, error; | ||||
romfile = get_config_value("lpc.bootrom"); | |||||
if (romfile != NULL) { | if (romfile != NULL) { | ||||
error = bootrom_loadrom(ctx, romfile); | error = bootrom_loadrom(ctx, romfile); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* COM1 and COM2 */ | /* COM1 and COM2 */ | ||||
for (unit = 0; unit < LPC_UART_NUM; unit++) { | for (unit = 0; unit < LPC_UART_NUM; unit++) { | ||||
sc = &lpc_uart_softc[unit]; | sc = &lpc_uart_softc[unit]; | ||||
name = lpc_uart_names[unit]; | name = lpc_uart_names[unit]; | ||||
if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) { | if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) { | ||||
EPRINTLN("Unable to allocate resources for " | EPRINTLN("Unable to allocate resources for " | ||||
"LPC device %s", name); | "LPC device %s", name); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
pci_irq_reserve(sc->irq); | pci_irq_reserve(sc->irq); | ||||
sc->uart_softc = uart_init(lpc_uart_intr_assert, | sc->uart_softc = uart_init(lpc_uart_intr_assert, | ||||
lpc_uart_intr_deassert, sc); | lpc_uart_intr_deassert, sc); | ||||
if (uart_set_backend(sc->uart_softc, sc->opts) != 0) { | asprintf(&node_name, "lpc.%s.path", name); | ||||
backend = get_config_value(node_name); | |||||
free(node_name); | |||||
if (uart_set_backend(sc->uart_softc, backend) != 0) { | |||||
EPRINTLN("Unable to initialize backend '%s' " | EPRINTLN("Unable to initialize backend '%s' " | ||||
"for LPC device %s", sc->opts, name); | "for LPC device %s", backend, name); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
bzero(&iop, sizeof(struct inout_port)); | bzero(&iop, sizeof(struct inout_port)); | ||||
iop.name = name; | iop.name = name; | ||||
iop.port = sc->iobase; | iop.port = sc->iobase; | ||||
iop.size = UART_IO_BAR_SIZE; | iop.size = UART_IO_BAR_SIZE; | ||||
iop.flags = IOPORT_F_INOUT; | iop.flags = IOPORT_F_INOUT; | ||||
iop.handler = lpc_uart_io_handler; | iop.handler = lpc_uart_io_handler; | ||||
iop.arg = sc; | iop.arg = sc; | ||||
error = register_inout(&iop); | error = register_inout(&iop); | ||||
assert(error == 0); | assert(error == 0); | ||||
sc->enabled = 1; | sc->enabled = 1; | ||||
} | } | ||||
/* pc-testdev */ | /* pc-testdev */ | ||||
if (pctestdev_present) { | asprintf(&node_name, "lpc.%s", pctestdev_getname()); | ||||
if (get_config_bool_default(node_name, false)) { | |||||
error = pctestdev_init(ctx); | error = pctestdev_init(ctx); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
free(node_name); | |||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
pci_lpc_write_dsdt(struct pci_devinst *pi) | pci_lpc_write_dsdt(struct pci_devinst *pi) | ||||
{ | { | ||||
struct lpc_dsdt **ldpp, *ldp; | struct lpc_dsdt **ldpp, *ldp; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | pci_lpc_uart_dsdt(void) | ||||
struct lpc_uart_softc *sc; | struct lpc_uart_softc *sc; | ||||
int unit; | int unit; | ||||
for (unit = 0; unit < LPC_UART_NUM; unit++) { | for (unit = 0; unit < LPC_UART_NUM; unit++) { | ||||
sc = &lpc_uart_softc[unit]; | sc = &lpc_uart_softc[unit]; | ||||
if (!sc->enabled) | if (!sc->enabled) | ||||
continue; | continue; | ||||
dsdt_line(""); | dsdt_line(""); | ||||
dsdt_line("Device (%s)", lpc_uart_names[unit]); | dsdt_line("Device (%s)", lpc_uart_acpi_names[unit]); | ||||
dsdt_line("{"); | dsdt_line("{"); | ||||
dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); | dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); | ||||
dsdt_line(" Name (_UID, %d)", unit + 1); | dsdt_line(" Name (_UID, %d)", unit + 1); | ||||
dsdt_line(" Name (_CRS, ResourceTemplate ()"); | dsdt_line(" Name (_CRS, ResourceTemplate ()"); | ||||
dsdt_line(" {"); | dsdt_line(" {"); | ||||
dsdt_indent(2); | dsdt_indent(2); | ||||
dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); | dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); | ||||
dsdt_fixed_irq(sc->irq); | dsdt_fixed_irq(sc->irq); | ||||
Show All 37 Lines | |||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
#define LPC_DEV 0x7000 | #define LPC_DEV 0x7000 | ||||
#define LPC_VENDOR 0x8086 | #define LPC_VENDOR 0x8086 | ||||
static int | static int | ||||
pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | ||||
{ | { | ||||
/* | /* | ||||
* Do not allow more than one LPC bridge to be configured. | * Do not allow more than one LPC bridge to be configured. | ||||
*/ | */ | ||||
if (lpc_bridge != NULL) { | if (lpc_bridge != NULL) { | ||||
EPRINTLN("Only one LPC bridge is allowed."); | EPRINTLN("Only one LPC bridge is allowed."); | ||||
return (-1); | return (-1); | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |
The following gets printed to terminal on boot:
From main(), acpi_build() gets called, then basl_compile() where iasl(8) gets called via system(). The iasl command has stdout going /dev/null but not stderr (which are where the messages are printed to).
passing the -vi flag to iasl(8) will suppress the warnings, here's a diff for context, https://reviews.freebsd.org/differential/diff/82835/
I haven't figured out how to add a suggestion on a file that isn't in the review, hence the provided diff.