aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/bhyve/pci_lpc.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2014-01-02 21:26:59 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2014-01-02 21:26:59 +0000
commite6c8bc291ab90fd23b17b330fe5323a535a691b8 (patch)
treec01bbcb7f17a6da8be3f9a9ffb1c43ab4f14ee6c /usr.sbin/bhyve/pci_lpc.c
parent27fd75d2c841729eebe293f9218277e308c1c3a8 (diff)
downloadsrc-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.c87
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
};