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)
This commit is contained in:
parent
27fd75d2c8
commit
e6c8bc291a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=260206
@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -67,6 +68,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "bhyverun.h"
|
||||
#include "acpi.h"
|
||||
#include "pci_emul.h"
|
||||
|
||||
/*
|
||||
* Define the base address of the ACPI tables, and the offsets to
|
||||
@ -98,6 +100,13 @@ static uint32_t hpet_capabilities;
|
||||
static char basl_template[MAXPATHLEN];
|
||||
static char basl_stemplate[MAXPATHLEN];
|
||||
|
||||
/*
|
||||
* State for dsdt_line(), dsdt_indent(), and dsdt_unindent().
|
||||
*/
|
||||
static FILE *dsdt_fp;
|
||||
static int dsdt_indent_level;
|
||||
static int dsdt_error;
|
||||
|
||||
struct basl_fio {
|
||||
int fd;
|
||||
FILE *fp;
|
||||
@ -606,119 +615,122 @@ basl_fwrite_facs(FILE *fp)
|
||||
return (errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper routines for writing to the DSDT from other modules.
|
||||
*/
|
||||
void
|
||||
dsdt_line(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
if (dsdt_error != 0)
|
||||
return;
|
||||
|
||||
if (strcmp(fmt, "") != 0) {
|
||||
if (dsdt_indent_level != 0)
|
||||
EFPRINTF(dsdt_fp, "%*c", dsdt_indent_level * 2, ' ');
|
||||
va_start(ap, fmt);
|
||||
if (vfprintf(dsdt_fp, fmt, ap) < 0)
|
||||
goto err_exit;
|
||||
va_end(ap);
|
||||
}
|
||||
EFPRINTF(dsdt_fp, "\n");
|
||||
return;
|
||||
|
||||
err_exit:
|
||||
dsdt_error = errno;
|
||||
}
|
||||
|
||||
void
|
||||
dsdt_indent(int levels)
|
||||
{
|
||||
|
||||
dsdt_indent_level += levels;
|
||||
assert(dsdt_indent_level >= 0);
|
||||
}
|
||||
|
||||
void
|
||||
dsdt_unindent(int levels)
|
||||
{
|
||||
|
||||
assert(dsdt_indent_level >= levels);
|
||||
dsdt_indent_level -= levels;
|
||||
}
|
||||
|
||||
void
|
||||
dsdt_fixed_ioport(uint16_t iobase, uint16_t length)
|
||||
{
|
||||
|
||||
dsdt_line("IO (Decode16,");
|
||||
dsdt_line(" 0x%04X, // Range Minimum", iobase);
|
||||
dsdt_line(" 0x%04X, // Range Maximum", iobase);
|
||||
dsdt_line(" 0x01, // Alignment");
|
||||
dsdt_line(" 0x%02X, // Length", length);
|
||||
dsdt_line(" )");
|
||||
}
|
||||
|
||||
void
|
||||
dsdt_fixed_irq(uint8_t irq)
|
||||
{
|
||||
|
||||
dsdt_line("IRQNoFlags ()");
|
||||
dsdt_line(" {%d}", irq);
|
||||
}
|
||||
|
||||
void
|
||||
dsdt_fixed_mem32(uint32_t base, uint32_t length)
|
||||
{
|
||||
|
||||
dsdt_line("Memory32Fixed (ReadWrite,");
|
||||
dsdt_line(" 0x%08X, // Address Base", base);
|
||||
dsdt_line(" 0x%08X, // Address Length", length);
|
||||
dsdt_line(" )");
|
||||
}
|
||||
|
||||
static int
|
||||
basl_fwrite_dsdt(FILE *fp)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
dsdt_fp = fp;
|
||||
dsdt_error = 0;
|
||||
dsdt_indent_level = 0;
|
||||
|
||||
EFPRINTF(fp, "/*\n");
|
||||
EFPRINTF(fp, " * bhyve DSDT template\n");
|
||||
EFPRINTF(fp, " */\n");
|
||||
EFPRINTF(fp, "DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
|
||||
"\"BHYVE \", \"BVDSDT \", 0x00000001)\n");
|
||||
EFPRINTF(fp, "{\n");
|
||||
EFPRINTF(fp, " Name (_S5, Package (0x02)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " 0x05,\n");
|
||||
EFPRINTF(fp, " Zero,\n");
|
||||
EFPRINTF(fp, " })\n");
|
||||
EFPRINTF(fp, " Scope (_SB)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Device (PCI0)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0A03\"))\n");
|
||||
EFPRINTF(fp, " Name (_ADR, Zero)\n");
|
||||
EFPRINTF(fp, " Name (_UID, One)\n");
|
||||
EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " WordBusNumber (ResourceProducer, MinFixed,"
|
||||
"MaxFixed, PosDecode,\n");
|
||||
EFPRINTF(fp, " 0x0000, // Granularity\n");
|
||||
EFPRINTF(fp, " 0x0000, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0x00FF, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x0000, // Transl Offset\n");
|
||||
EFPRINTF(fp, " 0x0100, // Length\n");
|
||||
EFPRINTF(fp, " ,, )\n");
|
||||
EFPRINTF(fp, " IO (Decode16,\n");
|
||||
EFPRINTF(fp, " 0x0CF8, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0x0CF8, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x01, // Alignment\n");
|
||||
EFPRINTF(fp, " 0x08, // Length\n");
|
||||
EFPRINTF(fp, " )\n");
|
||||
EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
|
||||
"PosDecode, EntireRange,\n");
|
||||
EFPRINTF(fp, " 0x0000, // Granularity\n");
|
||||
EFPRINTF(fp, " 0x0000, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0x0CF7, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x0000, // Transl Offset\n");
|
||||
EFPRINTF(fp, " 0x0CF8, // Length\n");
|
||||
EFPRINTF(fp, " ,, , TypeStatic)\n");
|
||||
EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
|
||||
"PosDecode, EntireRange,\n");
|
||||
EFPRINTF(fp, " 0x0000, // Granularity\n");
|
||||
EFPRINTF(fp, " 0x0D00, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0xFFFF, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x0000, // Transl Offset\n");
|
||||
EFPRINTF(fp, " 0xF300, // Length\n");
|
||||
EFPRINTF(fp, " ,, , TypeStatic)\n");
|
||||
EFPRINTF(fp, " })\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
EFPRINTF(fp, "\n");
|
||||
EFPRINTF(fp, " Scope (_SB.PCI0)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Device (ISA)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Name (_ADR, 0x00010000)\n");
|
||||
EFPRINTF(fp, " OperationRegion (P40C, PCI_Config, 0x60, 0x04)\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
dsdt_line("/*");
|
||||
dsdt_line(" * bhyve DSDT template");
|
||||
dsdt_line(" */");
|
||||
dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
|
||||
"\"BHYVE \", \"BVDSDT \", 0x00000001)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Name (_S5, Package (0x02)");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" 0x05,");
|
||||
dsdt_line(" Zero,");
|
||||
dsdt_line(" })");
|
||||
|
||||
EFPRINTF(fp, " Device (HPET)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Name (_HID, EISAID(\"PNP0103\"))\n");
|
||||
EFPRINTF(fp, " Name (_UID, 0)\n");
|
||||
EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " DWordMemory (ResourceConsumer, PosDecode, "
|
||||
"MinFixed, MaxFixed, NonCacheable, ReadWrite,\n");
|
||||
EFPRINTF(fp, " 0x00000000,\n");
|
||||
EFPRINTF(fp, " 0xFED00000,\n");
|
||||
EFPRINTF(fp, " 0xFED003FF,\n");
|
||||
EFPRINTF(fp, " 0x00000000,\n");
|
||||
EFPRINTF(fp, " 0x00000400\n");
|
||||
EFPRINTF(fp, " )\n");
|
||||
EFPRINTF(fp, " })\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
pci_write_dsdt();
|
||||
|
||||
EFPRINTF(fp, " }\n");
|
||||
EFPRINTF(fp, "\n");
|
||||
EFPRINTF(fp, " Scope (_SB.PCI0.ISA)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Device (RTC)\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0B00\"))\n");
|
||||
EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
|
||||
EFPRINTF(fp, " {\n");
|
||||
EFPRINTF(fp, " IO (Decode16,\n");
|
||||
EFPRINTF(fp, " 0x0070, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0x0070, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x10, // Alignment\n");
|
||||
EFPRINTF(fp, " 0x02, // Length\n");
|
||||
EFPRINTF(fp, " )\n");
|
||||
EFPRINTF(fp, " IRQNoFlags ()\n");
|
||||
EFPRINTF(fp, " {8}\n");
|
||||
EFPRINTF(fp, " IO (Decode16,\n");
|
||||
EFPRINTF(fp, " 0x0072, // Range Minimum\n");
|
||||
EFPRINTF(fp, " 0x0072, // Range Maximum\n");
|
||||
EFPRINTF(fp, " 0x02, // Alignment\n");
|
||||
EFPRINTF(fp, " 0x06, // Length\n");
|
||||
EFPRINTF(fp, " )\n");
|
||||
EFPRINTF(fp, " })\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
EFPRINTF(fp, " }\n");
|
||||
EFPRINTF(fp, "}\n");
|
||||
dsdt_line("");
|
||||
dsdt_line(" Scope (_SB.PCI0)");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" Device (HPET)");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" Name (_HID, EISAID(\"PNP0103\"))");
|
||||
dsdt_line(" Name (_UID, 0)");
|
||||
dsdt_line(" Name (_CRS, ResourceTemplate ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_indent(4);
|
||||
dsdt_fixed_mem32(0xFED00000, 0x400);
|
||||
dsdt_unindent(4);
|
||||
dsdt_line(" })");
|
||||
dsdt_line(" }");
|
||||
dsdt_line(" }");
|
||||
dsdt_line("}");
|
||||
|
||||
if (dsdt_error != 0)
|
||||
return (dsdt_error);
|
||||
|
||||
EFFLUSH(fp);
|
||||
|
||||
|
@ -43,5 +43,11 @@
|
||||
struct vmctx;
|
||||
|
||||
int acpi_build(struct vmctx *ctx, int ncpu);
|
||||
void dsdt_line(const char *fmt, ...);
|
||||
void dsdt_fixed_ioport(uint16_t iobase, uint16_t length);
|
||||
void dsdt_fixed_irq(uint8_t irq);
|
||||
void dsdt_fixed_mem32(uint32_t base, uint32_t length);
|
||||
void dsdt_indent(int levels);
|
||||
void dsdt_unindent(int levels);
|
||||
|
||||
#endif /* _ACPI_H_ */
|
||||
|
@ -35,7 +35,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "acpi.h"
|
||||
#include "inout.h"
|
||||
#include "pci_lpc.h"
|
||||
|
||||
#define IO_ICU1 0x20
|
||||
#define IO_ICU2 0xA0
|
||||
@ -65,3 +67,23 @@ INOUT_PORT(atpic, IO_ICU1, IOPORT_F_INOUT, atpic_handler);
|
||||
INOUT_PORT(atpic, IO_ICU1 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
|
||||
INOUT_PORT(atpic, IO_ICU2, IOPORT_F_INOUT, atpic_handler);
|
||||
INOUT_PORT(atpic, IO_ICU2 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
|
||||
|
||||
static void
|
||||
atpic_dsdt(void)
|
||||
{
|
||||
|
||||
dsdt_line("");
|
||||
dsdt_line("Device (PIC)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Name (_HID, EisaId (\"PNP0000\"))");
|
||||
dsdt_line(" Name (_CRS, ResourceTemplate ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_indent(2);
|
||||
dsdt_fixed_ioport(IO_ICU1, 2);
|
||||
dsdt_fixed_ioport(IO_ICU2, 2);
|
||||
dsdt_fixed_irq(2);
|
||||
dsdt_unindent(2);
|
||||
dsdt_line(" })");
|
||||
dsdt_line("}");
|
||||
}
|
||||
LPC_DSDT(atpic_dsdt);
|
||||
|
@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "inout.h"
|
||||
#include "pci_lpc.h"
|
||||
|
||||
/*
|
||||
* EISA interrupt Level Control Register.
|
||||
@ -63,3 +64,4 @@ elcr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
}
|
||||
INOUT_PORT(elcr, ELCR_PORT + 0, IOPORT_F_INOUT, elcr_handler);
|
||||
INOUT_PORT(elcr, ELCR_PORT + 1, IOPORT_F_INOUT, elcr_handler);
|
||||
SYSRES_IO(ELCR_PORT, 2);
|
||||
|
@ -44,11 +44,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/vmm.h>
|
||||
#include <vmmapi.h>
|
||||
|
||||
#include "acpi.h"
|
||||
#include "bhyverun.h"
|
||||
#include "inout.h"
|
||||
#include "legacy_irq.h"
|
||||
#include "mem.h"
|
||||
#include "pci_emul.h"
|
||||
#include "pci_lpc.h"
|
||||
|
||||
#define CONF1_ADDR_PORT 0x0cf8
|
||||
#define CONF1_DATA_PORT 0x0cfc
|
||||
@ -93,6 +95,7 @@ static uint64_t pci_emul_membase64;
|
||||
static struct pci_devemu *pci_emul_finddev(char *name);
|
||||
|
||||
static int pci_emul_devices;
|
||||
static struct mem_range pci_mem_hole;
|
||||
|
||||
/*
|
||||
* I/O access
|
||||
@ -997,7 +1000,6 @@ pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
|
||||
int
|
||||
init_pci(struct vmctx *ctx)
|
||||
{
|
||||
struct mem_range memp;
|
||||
struct pci_devemu *pde;
|
||||
struct slotinfo *si;
|
||||
size_t lowmem;
|
||||
@ -1035,19 +1037,100 @@ init_pci(struct vmctx *ctx)
|
||||
error = vm_get_memory_seg(ctx, 0, &lowmem, NULL);
|
||||
assert(error == 0);
|
||||
|
||||
memset(&memp, 0, sizeof(struct mem_range));
|
||||
memp.name = "PCI hole";
|
||||
memp.flags = MEM_F_RW;
|
||||
memp.base = lowmem;
|
||||
memp.size = (4ULL * 1024 * 1024 * 1024) - lowmem;
|
||||
memp.handler = pci_emul_fallback_handler;
|
||||
memset(&pci_mem_hole, 0, sizeof(struct mem_range));
|
||||
pci_mem_hole.name = "PCI hole";
|
||||
pci_mem_hole.flags = MEM_F_RW;
|
||||
pci_mem_hole.base = lowmem;
|
||||
pci_mem_hole.size = (4ULL * 1024 * 1024 * 1024) - lowmem;
|
||||
pci_mem_hole.handler = pci_emul_fallback_handler;
|
||||
|
||||
error = register_mem_fallback(&memp);
|
||||
error = register_mem_fallback(&pci_mem_hole);
|
||||
assert(error == 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
pci_write_dsdt(void)
|
||||
{
|
||||
struct pci_devinst *pi;
|
||||
int slot, func;
|
||||
|
||||
dsdt_indent(1);
|
||||
dsdt_line("Scope (_SB)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Device (PCI0)");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))");
|
||||
dsdt_line(" Name (_ADR, Zero)");
|
||||
dsdt_line(" Name (_CRS, ResourceTemplate ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" WordBusNumber (ResourceProducer, MinFixed, "
|
||||
"MaxFixed, PosDecode,");
|
||||
dsdt_line(" 0x0000, // Granularity");
|
||||
dsdt_line(" 0x0000, // Range Minimum");
|
||||
dsdt_line(" 0x00FF, // Range Maximum");
|
||||
dsdt_line(" 0x0000, // Translation Offset");
|
||||
dsdt_line(" 0x0100, // Length");
|
||||
dsdt_line(" ,, )");
|
||||
dsdt_indent(3);
|
||||
dsdt_fixed_ioport(0xCF8, 8);
|
||||
dsdt_unindent(3);
|
||||
dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, "
|
||||
"PosDecode, EntireRange,");
|
||||
dsdt_line(" 0x0000, // Granularity");
|
||||
dsdt_line(" 0x0000, // Range Minimum");
|
||||
dsdt_line(" 0x0CF7, // Range Maximum");
|
||||
dsdt_line(" 0x0000, // Translation Offset");
|
||||
dsdt_line(" 0x0CF8, // Length");
|
||||
dsdt_line(" ,, , TypeStatic)");
|
||||
dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, "
|
||||
"PosDecode, EntireRange,");
|
||||
dsdt_line(" 0x0000, // Granularity");
|
||||
dsdt_line(" 0x0D00, // Range Minimum");
|
||||
dsdt_line(" 0xFFFF, // Range Maximum");
|
||||
dsdt_line(" 0x0000, // Translation Offset");
|
||||
dsdt_line(" 0xF300, // Length");
|
||||
dsdt_line(" ,, , TypeStatic)");
|
||||
dsdt_line(" DWordMemory (ResourceProducer, PosDecode, "
|
||||
"MinFixed, MaxFixed, NonCacheable, ReadWrite,");
|
||||
dsdt_line(" 0x00000000, // Granularity");
|
||||
dsdt_line(" 0x%08lX, // Range Minimum\n",
|
||||
pci_mem_hole.base);
|
||||
dsdt_line(" 0x%08X, // Range Maximum\n",
|
||||
PCI_EMUL_MEMLIMIT32 - 1);
|
||||
dsdt_line(" 0x00000000, // Translation Offset");
|
||||
dsdt_line(" 0x%08lX, // Length\n",
|
||||
PCI_EMUL_MEMLIMIT32 - pci_mem_hole.base);
|
||||
dsdt_line(" ,, , AddressRangeMemory, TypeStatic)");
|
||||
dsdt_line(" QWordMemory (ResourceProducer, PosDecode, "
|
||||
"MinFixed, MaxFixed, NonCacheable, ReadWrite,");
|
||||
dsdt_line(" 0x0000000000000000, // Granularity");
|
||||
dsdt_line(" 0x%016lX, // Range Minimum\n",
|
||||
PCI_EMUL_MEMBASE64);
|
||||
dsdt_line(" 0x%016lX, // Range Maximum\n",
|
||||
PCI_EMUL_MEMLIMIT64 - 1);
|
||||
dsdt_line(" 0x0000000000000000, // Translation Offset");
|
||||
dsdt_line(" 0x%016lX, // Length\n",
|
||||
PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64);
|
||||
dsdt_line(" ,, , AddressRangeMemory, TypeStatic)");
|
||||
dsdt_line(" })");
|
||||
|
||||
dsdt_indent(2);
|
||||
for (slot = 0; slot < MAXSLOTS; slot++) {
|
||||
for (func = 0; func < MAXFUNCS; func++) {
|
||||
pi = pci_slotinfo[slot][func].si_devi;
|
||||
if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL)
|
||||
pi->pi_d->pe_write_dsdt(pi);
|
||||
}
|
||||
}
|
||||
dsdt_unindent(2);
|
||||
|
||||
dsdt_line(" }");
|
||||
dsdt_line("}");
|
||||
dsdt_unindent(1);
|
||||
}
|
||||
|
||||
int
|
||||
pci_msi_enabled(struct pci_devinst *pi)
|
||||
{
|
||||
@ -1433,6 +1516,7 @@ pci_irq_port_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
}
|
||||
INOUT_PORT(pci_irq, 0xC00, IOPORT_F_OUT, pci_irq_port_handler);
|
||||
INOUT_PORT(pci_irq, 0xC01, IOPORT_F_OUT, pci_irq_port_handler);
|
||||
SYSRES_IO(0xC00, 2);
|
||||
|
||||
#define PCI_EMUL_TEST
|
||||
#ifdef PCI_EMUL_TEST
|
||||
|
@ -51,6 +51,9 @@ struct pci_devemu {
|
||||
int (*pe_init)(struct vmctx *, struct pci_devinst *,
|
||||
char *opts);
|
||||
|
||||
/* ACPI DSDT enumeration */
|
||||
void (*pe_write_dsdt)(struct pci_devinst *);
|
||||
|
||||
/* config space read/write callbacks */
|
||||
int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu,
|
||||
struct pci_devinst *pi, int offset,
|
||||
@ -213,6 +216,7 @@ int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum);
|
||||
int pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size,
|
||||
uint64_t value);
|
||||
uint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size);
|
||||
void pci_write_dsdt(void);
|
||||
|
||||
static __inline void
|
||||
pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)
|
||||
|
@ -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,11 +170,91 @@ 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
|
||||
};
|
||||
|
@ -29,6 +29,42 @@
|
||||
#ifndef _LPC_H_
|
||||
#define _LPC_H_
|
||||
|
||||
#include <sys/linker_set.h>
|
||||
|
||||
typedef void (*lpc_write_dsdt_t)(void);
|
||||
|
||||
struct lpc_dsdt {
|
||||
lpc_write_dsdt_t handler;
|
||||
};
|
||||
|
||||
#define LPC_DSDT(handler) \
|
||||
static struct lpc_dsdt __CONCAT(__lpc_dsdt, __LINE__) = { \
|
||||
(handler), \
|
||||
}; \
|
||||
DATA_SET(lpc_dsdt_set, __CONCAT(__lpc_dsdt, __LINE__))
|
||||
|
||||
enum lpc_sysres_type {
|
||||
LPC_SYSRES_IO,
|
||||
LPC_SYSRES_MEM
|
||||
};
|
||||
|
||||
struct lpc_sysres {
|
||||
enum lpc_sysres_type type;
|
||||
uint32_t base;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
#define LPC_SYSRES(type, base, length) \
|
||||
static struct lpc_sysres __CONCAT(__lpc_sysres, __LINE__) = { \
|
||||
(type), \
|
||||
(base), \
|
||||
(length) \
|
||||
}; \
|
||||
DATA_SET(lpc_sysres_set, __CONCAT(__lpc_sysres, __LINE__))
|
||||
|
||||
#define SYSRES_IO(base, length) LPC_SYSRES(LPC_SYSRES_IO, base, length)
|
||||
#define SYSRES_MEM(base, length) LPC_SYSRES(LPC_SYSRES_MEM, base, length)
|
||||
|
||||
int lpc_device_parse(const char *opt);
|
||||
|
||||
#endif
|
||||
|
@ -42,9 +42,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <vmmapi.h>
|
||||
|
||||
#include "acpi.h"
|
||||
#include "bhyverun.h"
|
||||
#include "inout.h"
|
||||
#include "mevent.h"
|
||||
#include "pci_lpc.h"
|
||||
#include "pit_8254.h"
|
||||
|
||||
#define TIMER_SEL_MASK 0xc0
|
||||
@ -268,3 +270,22 @@ INOUT_PORT(8254, TIMER_MODE, IOPORT_F_OUT, pit_8254_handler);
|
||||
INOUT_PORT(8254, TIMER_CNTR0, IOPORT_F_INOUT, pit_8254_handler);
|
||||
INOUT_PORT(8254, TIMER_CNTR1, IOPORT_F_INOUT, pit_8254_handler);
|
||||
INOUT_PORT(8254, TIMER_CNTR2, IOPORT_F_INOUT, pit_8254_handler);
|
||||
|
||||
static void
|
||||
pit_dsdt(void)
|
||||
{
|
||||
|
||||
dsdt_line("");
|
||||
dsdt_line("Device (TIMR)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))");
|
||||
dsdt_line(" Name (_CRS, ResourceTemplate ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_indent(2);
|
||||
dsdt_fixed_ioport(IO_TIMER1, 4);
|
||||
dsdt_fixed_irq(0);
|
||||
dsdt_unindent(2);
|
||||
dsdt_line(" })");
|
||||
dsdt_line("}");
|
||||
}
|
||||
LPC_DSDT(pit_dsdt);
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "acpi.h"
|
||||
#include "inout.h"
|
||||
#include "mevent.h"
|
||||
#include "pci_lpc.h"
|
||||
|
||||
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct mevent *power_button;
|
||||
@ -248,6 +249,7 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
return (0);
|
||||
}
|
||||
INOUT_PORT(pm1_control, PM1A_CNT_ADDR, IOPORT_F_INOUT, pm1_control_handler);
|
||||
SYSRES_IO(PM1A_EVT_ADDR, 8);
|
||||
|
||||
/*
|
||||
* ACPI SMI Command Register
|
||||
@ -286,3 +288,4 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
return (0);
|
||||
}
|
||||
INOUT_PORT(smi_cmd, SMI_CMD, IOPORT_F_OUT, smi_cmd_handler);
|
||||
SYSRES_IO(SMI_CMD, 1);
|
||||
|
@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <assert.h>
|
||||
|
||||
#include "inout.h"
|
||||
#include "pci_lpc.h"
|
||||
|
||||
static int
|
||||
post_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
@ -49,3 +50,4 @@ post_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
||||
}
|
||||
|
||||
INOUT_PORT(post, 0x84, IOPORT_F_IN, post_data_handler);
|
||||
SYSRES_IO(0x84, 1);
|
||||
|
@ -40,7 +40,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/vmm.h>
|
||||
#include <vmmapi.h>
|
||||
|
||||
#include "acpi.h"
|
||||
#include "inout.h"
|
||||
#include "pci_lpc.h"
|
||||
#include "rtc.h"
|
||||
|
||||
#define IO_RTC 0x70
|
||||
@ -358,3 +360,24 @@ rtc_init(struct vmctx *ctx)
|
||||
|
||||
INOUT_PORT(rtc, IO_RTC, IOPORT_F_INOUT, rtc_addr_handler);
|
||||
INOUT_PORT(rtc, IO_RTC + 1, IOPORT_F_INOUT, rtc_data_handler);
|
||||
|
||||
static void
|
||||
rtc_dsdt(void)
|
||||
{
|
||||
|
||||
dsdt_line("");
|
||||
dsdt_line("Device (RTC)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Name (_HID, EisaId (\"PNP0B00\"))");
|
||||
dsdt_line(" Name (_CRS, ResourceTemplate ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_indent(2);
|
||||
dsdt_fixed_ioport(IO_RTC, 2);
|
||||
dsdt_fixed_irq(8);
|
||||
dsdt_unindent(2);
|
||||
dsdt_line(" })");
|
||||
dsdt_line("}");
|
||||
}
|
||||
LPC_DSDT(rtc_dsdt);
|
||||
|
||||
SYSRES_IO(0x72, 6);
|
||||
|
Loading…
Reference in New Issue
Block a user