diff options
author | John Baldwin <jhb@FreeBSD.org> | 2014-01-02 21:26:59 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2014-01-02 21:26:59 +0000 |
commit | e6c8bc291ab90fd23b17b330fe5323a535a691b8 (patch) | |
tree | c01bbcb7f17a6da8be3f9a9ffb1c43ab4f14ee6c /usr.sbin/bhyve/pci_lpc.c | |
parent | 27fd75d2c841729eebe293f9218277e308c1c3a8 (diff) | |
download | src-e6c8bc291ab90fd23b17b330fe5323a535a691b8.tar.gz src-e6c8bc291ab90fd23b17b330fe5323a535a691b8.zip |
Rework the DSDT generation code a bit to generate more accurate info about
LPC devices. Among other things, the LPC serial ports now appear as
ACPI devices.
- Move the info for the top-level PCI bus into the PCI emulation code and
add ResourceProducer entries for the memory ranges decoded by the bus
for memory BARs.
- Add a framework to allow each PCI emulation driver to optionally write
an entry into the DSDT under the \_SB_.PCI0 namespace. The LPC driver
uses this to write a node for the LPC bus (\_SB_.PCI0.ISA).
- Add a linker set to allow any LPC devices to write entries into the
DSDT below the LPC node.
- Move the existing DSDT block for the RTC to the RTC driver.
- Add DSDT nodes for the AT PIC, the 8254 ISA timer, and the LPC UART
devices.
- Add a "SuperIO" device under the LPC node to claim "system resources"
aling with a linker set to allow various drivers to add IO or memory
ranges that should be claimed as a system resource.
- Add system resource entries for the extended RTC IO range, the registers
used for ACPI power management, the ELCR, PCI interrupt routing register,
and post data register.
- Add various helper routines for generating DSDT entries.
Reviewed by: neel (earlier version)
Notes
Notes:
svn path=/head/; revision=260206
Diffstat (limited to 'usr.sbin/bhyve/pci_lpc.c')
-rw-r--r-- | usr.sbin/bhyve/pci_lpc.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c index 4157c5cb0c7e..a1e750d9bbf2 100644 --- a/usr.sbin/bhyve/pci_lpc.c +++ b/usr.sbin/bhyve/pci_lpc.c @@ -40,10 +40,15 @@ __FBSDID("$FreeBSD$"); #include <vmmapi.h> +#include "acpi.h" #include "inout.h" #include "pci_emul.h" +#include "pci_lpc.h" #include "uart_emul.h" +SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); +SET_DECLARE(lpc_sysres_set, struct lpc_sysres); + static struct pci_devinst *lpc_bridge; #define LPC_UART_NUM 2 @@ -52,6 +57,7 @@ static struct lpc_uart_softc { const char *opts; int iobase; int irq; + int enabled; } lpc_uart_softc[LPC_UART_NUM]; static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2" }; @@ -164,12 +170,92 @@ lpc_init(void) error = register_inout(&iop); assert(error == 0); + sc->enabled = 1; } return (0); } static void +pci_lpc_write_dsdt(struct pci_devinst *pi) +{ + struct lpc_dsdt **ldpp, *ldp; + + dsdt_line(""); + dsdt_line("Device (ISA)"); + dsdt_line("{"); + dsdt_line(" Name (_ADR, 0x%04X%04X)", pi->pi_slot, pi->pi_func); + dsdt_line(" OperationRegion (P40C, PCI_Config, 0x60, 0x04)"); + + dsdt_indent(1); + SET_FOREACH(ldpp, lpc_dsdt_set) { + ldp = *ldpp; + ldp->handler(); + } + dsdt_unindent(1); + + dsdt_line("}"); +} + +static void +pci_lpc_sysres_dsdt(void) +{ + struct lpc_sysres **lspp, *lsp; + + dsdt_line(""); + dsdt_line("Device (SIO)"); + dsdt_line("{"); + dsdt_line(" Name (_HID, EisaId (\"PNP0C02\"))"); + dsdt_line(" Name (_CRS, ResourceTemplate ()"); + dsdt_line(" {"); + + dsdt_indent(2); + SET_FOREACH(lspp, lpc_sysres_set) { + lsp = *lspp; + switch (lsp->type) { + case LPC_SYSRES_IO: + dsdt_fixed_ioport(lsp->base, lsp->length); + break; + case LPC_SYSRES_MEM: + dsdt_fixed_mem32(lsp->base, lsp->length); + break; + } + } + dsdt_unindent(2); + + dsdt_line(" })"); + dsdt_line("}"); +} +LPC_DSDT(pci_lpc_sysres_dsdt); + +static void +pci_lpc_uart_dsdt(void) +{ + struct lpc_uart_softc *sc; + int unit; + + for (unit = 0; unit < LPC_UART_NUM; unit++) { + sc = &lpc_uart_softc[unit]; + if (!sc->enabled) + continue; + dsdt_line(""); + dsdt_line("Device (%s)", lpc_uart_names[unit]); + dsdt_line("{"); + dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); + dsdt_line(" Name (_UID, %d)", unit + 1); + dsdt_line(" Name (_CRS, ResourceTemplate ()"); + dsdt_line(" {"); + dsdt_indent(2); + dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); + dsdt_fixed_irq(sc->irq); + dsdt_unindent(2); + dsdt_line(" })"); + dsdt_line("}"); + } +} +LPC_DSDT(pci_lpc_uart_dsdt); + +static void pci_lpc_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value) { @@ -211,6 +297,7 @@ pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) struct pci_devemu pci_de_lpc = { .pe_emu = "lpc", .pe_init = pci_lpc_init, + .pe_write_dsdt = pci_lpc_write_dsdt, .pe_barwrite = pci_lpc_write, .pe_barread = pci_lpc_read }; |