mirror of https://gitee.com/openkylin/qemu.git
pci, pc, acpi fixes, enhancements
This includes some pretty big changes: - pci master abort support by Marcel - pci IRQ API rework by Marcel - acpi generation support by myself Everything has gone through several revisions, latest versions have been on list for a while without any more comments, tested by several people. Please pull for 1.7. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) iQEcBAABAgAGBQJSXNO8AAoJECgfDbjSjVRp7VAH/0B73mCOiyVACGx7fazK3SGK X8TxZWVtG5A77ISqKyrtjLAhK9DCQjEzQTbMNhXHM3Ar6crwo7nJZnQvH2Gh1X2p 34BOQSVc4rtXz5pwDIr48dBLrxeslwXub79chUs+IK1/4RSn3h3nuS3k6JVkmLJN rcHMj4ljJmi4Hd9vOpmS1jo/a61usi36hhU7CMgcrsXzStZycBBzCozOB3VW8p1X /iwyf91YjmNPkn9gA3/aViGjszu8jE91dkA0C+ljwvcGbs2yEl3LCWEJfsMvoh5P 2M+k0XXbHwq/P9PFMa/2/lWOo4EO4Oxa+G/6QvovJrteYnktr+E9DqjU8pCT7yI= =CVfs -----END PGP SIGNATURE----- Merge remote-tracking branch 'mst/tags/for_anthony' into staging pci, pc, acpi fixes, enhancements This includes some pretty big changes: - pci master abort support by Marcel - pci IRQ API rework by Marcel - acpi generation support by myself Everything has gone through several revisions, latest versions have been on list for a while without any more comments, tested by several people. Please pull for 1.7. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Tue 15 Oct 2013 07:33:48 AM CEST using RSA key ID D28D5469 # gpg: Can't check signature: public key not found * mst/tags/for_anthony: (39 commits) ssdt-proc: update generated file ssdt: fix PBLK length i386: ACPI table generation code from seabios pc: use new api to add builtin tables acpi: add interface to access user-installed tables hpet: add API to find it pvpanic: add API to access io port ich9: APIs for pc guest info piix: APIs for pc guest info acpi/piix: add macros for acpi property names i386: define pc guest info loader: allow adding ROMs in done callbacks i386: add bios linker/loader loader: use file path size from fw_cfg.h acpi: ssdt pcihp: updat generated file acpi: pre-compiled ASL files acpi: add rules to compile ASL source i386: add ACPI table files from seabios q35: expose mmcfg size as a property q35: use macro for MCFG property name ... Message-id: 1381818560-18367-1-git-send-email-mst@redhat.com Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
commit
b0eb759fb2
|
@ -119,6 +119,7 @@ path_of() {
|
|||
# default parameters
|
||||
source_path=`dirname "$0"`
|
||||
cpu=""
|
||||
iasl="iasl"
|
||||
interp_prefix="/usr/gnemul/qemu-%M"
|
||||
static="no"
|
||||
cross_prefix=""
|
||||
|
@ -257,6 +258,8 @@ for opt do
|
|||
;;
|
||||
--cxx=*) CXX="$optarg"
|
||||
;;
|
||||
--iasl=*) iasl="$optarg"
|
||||
;;
|
||||
--source-path=*) source_path="$optarg"
|
||||
;;
|
||||
--cpu=*) cpu="$optarg"
|
||||
|
@ -1058,6 +1061,7 @@ echo "Advanced options (experts only):"
|
|||
echo " --source-path=PATH path of source code [$source_path]"
|
||||
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
|
||||
echo " --cc=CC use C compiler CC [$cc]"
|
||||
echo " --iasl=IASL use ACPI compiler IASL [$iasl]"
|
||||
echo " --host-cc=CC use C compiler CC [$host_cc] for code run at"
|
||||
echo " build time"
|
||||
echo " --cxx=CXX use C++ compiler CXX [$cxx]"
|
||||
|
@ -4234,6 +4238,9 @@ else
|
|||
fi
|
||||
echo "PYTHON=$python" >> $config_host_mak
|
||||
echo "CC=$cc" >> $config_host_mak
|
||||
if $iasl -h > /dev/null 2>&1; then
|
||||
echo "IASL=$iasl" >> $config_host_mak
|
||||
fi
|
||||
echo "CC_I386=$cc_i386" >> $config_host_mak
|
||||
echo "HOST_CC=$host_cc" >> $config_host_mak
|
||||
echo "CXX=$cxx" >> $config_host_mak
|
||||
|
@ -4686,7 +4693,7 @@ for rom in seabios vgabios ; do
|
|||
echo "BCC=bcc" >> $config_mak
|
||||
echo "CPP=$cpp" >> $config_mak
|
||||
echo "OBJCOPY=objcopy" >> $config_mak
|
||||
echo "IASL=iasl" >> $config_mak
|
||||
echo "IASL=$iasl" >> $config_mak
|
||||
echo "LD=$ld" >> $config_mak
|
||||
done
|
||||
|
||||
|
|
|
@ -80,6 +80,10 @@ guest. This is done with memory_region_add_subregion_overlap(), which
|
|||
allows the region to overlap any other region in the same container, and
|
||||
specifies a priority that allows the core to decide which of two regions at
|
||||
the same address are visible (highest wins).
|
||||
Priority values are signed, and the default value is zero. This means that
|
||||
you can use memory_region_add_subregion_overlap() both to specify a region
|
||||
that must sit 'above' any others (with a positive priority) and also a
|
||||
background region that sits 'below' others (with a negative priority).
|
||||
|
||||
Visibility
|
||||
----------
|
||||
|
|
|
@ -309,6 +309,46 @@ out:
|
|||
error_propagate(errp, err);
|
||||
}
|
||||
|
||||
static bool acpi_table_builtin = false;
|
||||
|
||||
void acpi_table_add_builtin(const QemuOpts *opts, Error **errp)
|
||||
{
|
||||
acpi_table_builtin = true;
|
||||
acpi_table_add(opts, errp);
|
||||
}
|
||||
|
||||
unsigned acpi_table_len(void *current)
|
||||
{
|
||||
struct acpi_table_header *hdr = current - sizeof(hdr->_length);
|
||||
return hdr->_length;
|
||||
}
|
||||
|
||||
static
|
||||
void *acpi_table_hdr(void *h)
|
||||
{
|
||||
struct acpi_table_header *hdr = h;
|
||||
return &hdr->sig;
|
||||
}
|
||||
|
||||
uint8_t *acpi_table_first(void)
|
||||
{
|
||||
if (acpi_table_builtin || !acpi_tables) {
|
||||
return NULL;
|
||||
}
|
||||
return acpi_table_hdr(acpi_tables + ACPI_TABLE_PFX_SIZE);
|
||||
}
|
||||
|
||||
uint8_t *acpi_table_next(uint8_t *current)
|
||||
{
|
||||
uint8_t *next = current + acpi_table_len(current);
|
||||
|
||||
if (next - acpi_tables >= acpi_tables_len) {
|
||||
return NULL;
|
||||
} else {
|
||||
return acpi_table_hdr(next);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_notify_wakeup(Notifier *notifier, void *data)
|
||||
{
|
||||
ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
#include "hw/hw.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "qemu/timer.h"
|
||||
|
@ -228,3 +229,26 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
|
|||
pm->powerdown_notifier.notify = pm_powerdown_req;
|
||||
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
|
||||
}
|
||||
|
||||
static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
ICH9LPCPMRegs *pm = opaque;
|
||||
uint32_t value = pm->pm_io_base + ICH9_PMIO_GPE0_STS;
|
||||
|
||||
visit_type_uint32(v, &value, name, errp);
|
||||
}
|
||||
|
||||
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
|
||||
{
|
||||
static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
|
||||
|
||||
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
|
||||
&pm->pm_io_base, errp);
|
||||
object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
|
||||
ich9_pm_get_gpe0_blk,
|
||||
NULL, NULL, pm, NULL);
|
||||
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
|
||||
&gpe0_len, errp);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "exec/ioport.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/acpi/piix4.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
|
@ -69,6 +70,8 @@ typedef struct PIIX4PMState {
|
|||
/*< public >*/
|
||||
|
||||
MemoryRegion io;
|
||||
uint32_t io_base;
|
||||
|
||||
MemoryRegion io_gpe;
|
||||
MemoryRegion io_pci;
|
||||
MemoryRegion io_cpu;
|
||||
|
@ -152,14 +155,13 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
|
|||
static void pm_io_space_update(PIIX4PMState *s)
|
||||
{
|
||||
PCIDevice *d = PCI_DEVICE(s);
|
||||
uint32_t pm_io_base;
|
||||
|
||||
pm_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
|
||||
pm_io_base &= 0xffc0;
|
||||
s->io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
|
||||
s->io_base &= 0xffc0;
|
||||
|
||||
memory_region_transaction_begin();
|
||||
memory_region_set_enabled(&s->io, d->config[0x80] & 1);
|
||||
memory_region_set_address(&s->io, pm_io_base);
|
||||
memory_region_set_address(&s->io, s->io_base);
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
|
@ -407,6 +409,28 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
|
|||
(memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
|
||||
}
|
||||
|
||||
static void piix4_pm_add_propeties(PIIX4PMState *s)
|
||||
{
|
||||
static const uint8_t acpi_enable_cmd = ACPI_ENABLE;
|
||||
static const uint8_t acpi_disable_cmd = ACPI_DISABLE;
|
||||
static const uint32_t gpe0_blk = GPE_BASE;
|
||||
static const uint32_t gpe0_blk_len = GPE_LEN;
|
||||
static const uint16_t sci_int = 9;
|
||||
|
||||
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
|
||||
&acpi_enable_cmd, NULL);
|
||||
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
|
||||
&acpi_disable_cmd, NULL);
|
||||
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
|
||||
&gpe0_blk, NULL);
|
||||
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
|
||||
&gpe0_blk_len, NULL);
|
||||
object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
|
||||
&sci_int, NULL);
|
||||
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
|
||||
&s->io_base, NULL);
|
||||
}
|
||||
|
||||
static int piix4_pm_initfn(PCIDevice *dev)
|
||||
{
|
||||
PIIX4PMState *s = PIIX4_PM(dev);
|
||||
|
@ -456,9 +480,21 @@ static int piix4_pm_initfn(PCIDevice *dev)
|
|||
|
||||
piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
|
||||
|
||||
piix4_pm_add_propeties(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object *piix4_pm_find(void)
|
||||
{
|
||||
bool ambig;
|
||||
Object *o = object_resolve_path_type("", TYPE_PIIX4_PM, &ambig);
|
||||
|
||||
if (ambig || !o) {
|
||||
return NULL;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
|
||||
qemu_irq sci_irq, qemu_irq smi_irq,
|
||||
int kvm_enabled, FWCfgState *fw_cfg)
|
||||
|
@ -489,9 +525,9 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
|
|||
|
||||
static Property piix4_pm_properties[] = {
|
||||
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
|
||||
DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0),
|
||||
DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0),
|
||||
DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2),
|
||||
DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
|
||||
DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
|
||||
DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
|
|
@ -280,12 +280,12 @@ static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
|
|||
if (level) {
|
||||
s->glob_sta |= masks[r - s->bm_regs];
|
||||
dolog ("set irq level=1\n");
|
||||
qemu_set_irq (s->dev.irq[0], 1);
|
||||
pci_irq_assert(&s->dev);
|
||||
}
|
||||
else {
|
||||
s->glob_sta &= ~masks[r - s->bm_regs];
|
||||
dolog ("set irq level=0\n");
|
||||
qemu_set_irq (s->dev.irq[0], 0);
|
||||
pci_irq_deassert(&s->dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ static void es1370_update_status (ES1370State *s, uint32_t new_status)
|
|||
else {
|
||||
s->status = new_status & ~STAT_INTR;
|
||||
}
|
||||
qemu_set_irq (s->dev.irq[0], !!level);
|
||||
pci_set_irq(&s->dev, !!level);
|
||||
}
|
||||
|
||||
static void es1370_reset (ES1370State *s)
|
||||
|
@ -349,7 +349,7 @@ static void es1370_reset (ES1370State *s)
|
|||
s->dac_voice[i] = NULL;
|
||||
}
|
||||
}
|
||||
qemu_irq_lower (s->dev.irq[0]);
|
||||
pci_irq_deassert(&s->dev);
|
||||
}
|
||||
|
||||
static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)
|
||||
|
|
|
@ -269,7 +269,7 @@ static void intel_hda_update_irq(IntelHDAState *d)
|
|||
msi_notify(&d->pci, 0);
|
||||
}
|
||||
} else {
|
||||
qemu_set_irq(d->pci.irq[0], level);
|
||||
pci_set_irq(&d->pci, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
|
|||
if (msix_enabled(&(n->parent_obj))) {
|
||||
msix_notify(&(n->parent_obj), cq->vector);
|
||||
} else {
|
||||
qemu_irq_pulse(n->parent_obj.irq[0]);
|
||||
pci_irq_pulse(&n->parent_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ static int serial_pci_init(PCIDevice *dev)
|
|||
}
|
||||
|
||||
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
|
||||
s->irq = pci->dev.irq[0];
|
||||
s->irq = pci_allocate_irq(&pci->dev);
|
||||
|
||||
memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
|
||||
pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
|
||||
|
@ -79,7 +79,7 @@ static void multi_serial_irq_mux(void *opaque, int n, int level)
|
|||
pending = 1;
|
||||
}
|
||||
}
|
||||
qemu_set_irq(pci->dev.irq[0], pending);
|
||||
pci_set_irq(&pci->dev, pending);
|
||||
}
|
||||
|
||||
static int multi_serial_pci_init(PCIDevice *dev)
|
||||
|
@ -132,6 +132,7 @@ static void serial_pci_exit(PCIDevice *dev)
|
|||
|
||||
serial_exit_core(s);
|
||||
memory_region_destroy(&s->io);
|
||||
qemu_free_irq(s->irq);
|
||||
}
|
||||
|
||||
static void multi_serial_pci_exit(PCIDevice *dev)
|
||||
|
|
|
@ -134,8 +134,8 @@ static void tpci200_set_irq(void *opaque, int intno, int level)
|
|||
/* Check if the interrupt is edge sensitive */
|
||||
if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) {
|
||||
if (level) {
|
||||
qemu_set_irq(dev->dev.irq[0], !dev->int_set);
|
||||
qemu_set_irq(dev->dev.irq[0], dev->int_set);
|
||||
pci_set_irq(&dev->dev, !dev->int_set);
|
||||
pci_set_irq(&dev->dev, dev->int_set);
|
||||
}
|
||||
} else {
|
||||
unsigned i, j;
|
||||
|
@ -153,10 +153,10 @@ static void tpci200_set_irq(void *opaque, int intno, int level)
|
|||
}
|
||||
|
||||
if (level_status && !dev->int_set) {
|
||||
qemu_irq_raise(dev->dev.irq[0]);
|
||||
pci_irq_assert(&dev->dev);
|
||||
dev->int_set = 1;
|
||||
} else if (!level_status && dev->int_set) {
|
||||
qemu_irq_lower(dev->dev.irq[0]);
|
||||
pci_irq_deassert(&dev->dev);
|
||||
dev->int_set = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,17 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
|
|||
return qemu_extend_irqs(NULL, 0, handler, opaque, n);
|
||||
}
|
||||
|
||||
qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
|
||||
{
|
||||
struct IRQState *irq;
|
||||
|
||||
irq = g_new(struct IRQState, 1);
|
||||
irq->handler = handler;
|
||||
irq->opaque = opaque;
|
||||
irq->n = n;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void qemu_free_irqs(qemu_irq *s)
|
||||
{
|
||||
|
@ -75,6 +86,11 @@ void qemu_free_irqs(qemu_irq *s)
|
|||
g_free(s);
|
||||
}
|
||||
|
||||
void qemu_free_irq(qemu_irq irq)
|
||||
{
|
||||
g_free(irq);
|
||||
}
|
||||
|
||||
static void qemu_notirq(void *opaque, int line, int level)
|
||||
{
|
||||
struct IRQState *irq = opaque;
|
||||
|
|
|
@ -663,7 +663,7 @@ int rom_add_file(const char *file, const char *fw_dir,
|
|||
rom_insert(rom);
|
||||
if (rom->fw_file && fw_cfg) {
|
||||
const char *basename;
|
||||
char fw_file_name[56];
|
||||
char fw_file_name[FW_CFG_MAX_FILE_PATH];
|
||||
void *data;
|
||||
|
||||
basename = strrchr(rom->fw_file, '/');
|
||||
|
@ -700,10 +700,12 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
int rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr)
|
||||
void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr, const char *fw_file_name,
|
||||
FWCfgReadCallback fw_callback, void *callback_opaque)
|
||||
{
|
||||
Rom *rom;
|
||||
void *data = NULL;
|
||||
|
||||
rom = g_malloc0(sizeof(*rom));
|
||||
rom->name = g_strdup(name);
|
||||
|
@ -713,7 +715,22 @@ int rom_add_blob(const char *name, const void *blob, size_t len,
|
|||
rom->data = g_malloc0(rom->datasize);
|
||||
memcpy(rom->data, blob, len);
|
||||
rom_insert(rom);
|
||||
return 0;
|
||||
if (fw_file_name && fw_cfg) {
|
||||
char devpath[100];
|
||||
|
||||
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
|
||||
|
||||
if (rom_file_in_ram) {
|
||||
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
|
||||
} else {
|
||||
data = rom->data;
|
||||
}
|
||||
|
||||
fw_cfg_add_file_callback(fw_cfg, fw_file_name,
|
||||
fw_callback, callback_opaque,
|
||||
data, rom->romsize);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* This function is specific for elf program because we don't need to allocate
|
||||
|
@ -795,10 +812,14 @@ int rom_load_all(void)
|
|||
memory_region_unref(section.mr);
|
||||
}
|
||||
qemu_register_reset(rom_reset, NULL);
|
||||
roms_loaded = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rom_load_done(void)
|
||||
{
|
||||
roms_loaded = 1;
|
||||
}
|
||||
|
||||
void rom_set_fw(FWCfgState *f)
|
||||
{
|
||||
fw_cfg = f;
|
||||
|
|
|
@ -49,7 +49,7 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
|||
}
|
||||
|
||||
static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
|
||||
bool may_overlap, unsigned priority)
|
||||
bool may_overlap, int priority)
|
||||
{
|
||||
assert(n >= 0 && n < dev->num_mmio);
|
||||
|
||||
|
@ -81,7 +81,7 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
|
|||
}
|
||||
|
||||
void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
|
||||
unsigned priority)
|
||||
int priority)
|
||||
{
|
||||
sysbus_mmio_map_common(dev, n, addr, true, priority);
|
||||
}
|
||||
|
|
|
@ -1101,7 +1101,7 @@ static void qxl_update_irq(PCIQXLDevice *d)
|
|||
uint32_t pending = le32_to_cpu(d->ram->int_pending);
|
||||
uint32_t mask = le32_to_cpu(d->ram->int_mask);
|
||||
int level = !!(pending & mask);
|
||||
qemu_set_irq(d->pci.irq[0], level);
|
||||
pci_set_irq(&d->pci, level);
|
||||
qxl_ring_set_dirty(d);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,3 +5,30 @@ obj-y += pc_sysfw.o
|
|||
obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
|
||||
|
||||
obj-y += kvmvapic.o
|
||||
obj-y += acpi-build.o
|
||||
obj-y += bios-linker-loader.o
|
||||
hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
|
||||
hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
|
||||
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex
|
||||
|
||||
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
|
||||
; then echo "$(2)"; else echo "$(3)"; fi ;)
|
||||
|
||||
ifdef IASL
|
||||
#IASL Present. Generate hex files from .dsl
|
||||
hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
|
||||
$(call quiet-command, cpp -P $< -o $*.dsl.i.orig, " CPP $(TARGET_DIR)$*.dsl.i.orig")
|
||||
$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, " ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
|
||||
$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ," IASL $(TARGET_DIR)$*.dsl.i")
|
||||
$(call quiet-command, $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, " ACPI_EXTRACT $(TARGET_DIR)$*.off")
|
||||
$(call quiet-command, cat $*.off > $@, " CAT $(TARGET_DIR)$@")
|
||||
else
|
||||
#IASL Not present. Restore pre-generated hex files.
|
||||
hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.hex.generated
|
||||
$(call quiet-command, cp -f $< $@, " CP $(TARGET_DIR)$@")
|
||||
endif
|
||||
|
||||
.PHONY: cleanhex
|
||||
cleanhex:
|
||||
rm -f hw/i386/*hex
|
||||
clean: cleanhex
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
|
||||
#ifndef HW_I386_ACPI_BUILD_H
|
||||
#define HW_I386_ACPI_BUILD_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
void acpi_setup(PcGuestInfo *);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef QEMU_ACPI_DEFS_H
|
||||
#define QEMU_ACPI_DEFS_H
|
||||
|
||||
enum {
|
||||
ACPI_FADT_F_WBINVD,
|
||||
ACPI_FADT_F_WBINVD_FLUSH,
|
||||
ACPI_FADT_F_PROC_C1,
|
||||
ACPI_FADT_F_P_LVL2_UP,
|
||||
ACPI_FADT_F_PWR_BUTTON,
|
||||
ACPI_FADT_F_SLP_BUTTON,
|
||||
ACPI_FADT_F_FIX_RTC,
|
||||
ACPI_FADT_F_RTC_S4,
|
||||
ACPI_FADT_F_TMR_VAL_EXT,
|
||||
ACPI_FADT_F_DCK_CAP,
|
||||
ACPI_FADT_F_RESET_REG_SUP,
|
||||
ACPI_FADT_F_SEALED_CASE,
|
||||
ACPI_FADT_F_HEADLESS,
|
||||
ACPI_FADT_F_CPU_SW_SLP,
|
||||
ACPI_FADT_F_PCI_EXP_WAK,
|
||||
ACPI_FADT_F_USE_PLATFORM_CLOCK,
|
||||
ACPI_FADT_F_S4_RTC_STS_VALID,
|
||||
ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE,
|
||||
ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL,
|
||||
ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE,
|
||||
ACPI_FADT_F_HW_REDUCED_ACPI,
|
||||
ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE,
|
||||
};
|
||||
|
||||
/*
|
||||
* ACPI 2.0 Generic Address Space definition.
|
||||
*/
|
||||
struct Acpi20GenericAddress {
|
||||
uint8_t address_space_id;
|
||||
uint8_t register_bit_width;
|
||||
uint8_t register_bit_offset;
|
||||
uint8_t reserved;
|
||||
uint64_t address;
|
||||
} QEMU_PACKED;
|
||||
typedef struct Acpi20GenericAddress Acpi20GenericAddress;
|
||||
|
||||
#define ACPI_RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
|
||||
|
||||
struct AcpiRsdpDescriptor { /* Root System Descriptor Pointer */
|
||||
uint64_t signature; /* ACPI signature, contains "RSD PTR " */
|
||||
uint8_t checksum; /* To make sum of struct == 0 */
|
||||
uint8_t oem_id [6]; /* OEM identification */
|
||||
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
|
||||
uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
|
||||
uint32_t length; /* XSDT Length in bytes including hdr */
|
||||
uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
|
||||
uint8_t extended_checksum; /* Checksum of entire table */
|
||||
uint8_t reserved [3]; /* Reserved field must be 0 */
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor;
|
||||
|
||||
/* Table structure from Linux kernel (the ACPI tables are under the
|
||||
BSD license) */
|
||||
|
||||
|
||||
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
|
||||
uint32_t signature; /* ACPI signature (4 ASCII characters) */ \
|
||||
uint32_t length; /* Length of table, in bytes, including header */ \
|
||||
uint8_t revision; /* ACPI Specification minor version # */ \
|
||||
uint8_t checksum; /* To make sum of entire table == 0 */ \
|
||||
uint8_t oem_id [6]; /* OEM identification */ \
|
||||
uint8_t oem_table_id [8]; /* OEM table identification */ \
|
||||
uint32_t oem_revision; /* OEM revision number */ \
|
||||
uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */ \
|
||||
uint32_t asl_compiler_revision; /* ASL compiler revision number */
|
||||
|
||||
|
||||
struct AcpiTableHeader /* ACPI common table header */
|
||||
{
|
||||
ACPI_TABLE_HEADER_DEF
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiTableHeader AcpiTableHeader;
|
||||
|
||||
/*
|
||||
* ACPI 1.0 Fixed ACPI Description Table (FADT)
|
||||
*/
|
||||
#define ACPI_FACP_SIGNATURE 0x50434146 // FACP
|
||||
struct AcpiFadtDescriptorRev1
|
||||
{
|
||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||
uint32_t firmware_ctrl; /* Physical address of FACS */
|
||||
uint32_t dsdt; /* Physical address of DSDT */
|
||||
uint8_t model; /* System Interrupt Model */
|
||||
uint8_t reserved1; /* Reserved */
|
||||
uint16_t sci_int; /* System vector of SCI interrupt */
|
||||
uint32_t smi_cmd; /* Port address of SMI command port */
|
||||
uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
|
||||
uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
|
||||
uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
|
||||
uint8_t reserved2; /* Reserved - must be zero */
|
||||
uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
|
||||
uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
|
||||
uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
|
||||
uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
|
||||
uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
|
||||
uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
|
||||
uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
|
||||
uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
|
||||
uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
|
||||
uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
|
||||
uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
|
||||
uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
|
||||
uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
|
||||
uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
|
||||
uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
|
||||
uint8_t reserved3; /* Reserved */
|
||||
uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
|
||||
uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
|
||||
uint16_t flush_size; /* Size of area read to flush caches */
|
||||
uint16_t flush_stride; /* Stride used in flushing caches */
|
||||
uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
|
||||
uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
|
||||
uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
|
||||
uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
|
||||
uint8_t century; /* Index to century in RTC CMOS RAM */
|
||||
uint8_t reserved4; /* Reserved */
|
||||
uint8_t reserved4a; /* Reserved */
|
||||
uint8_t reserved4b; /* Reserved */
|
||||
uint32_t flags;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1;
|
||||
|
||||
/*
|
||||
* ACPI 1.0 Root System Description Table (RSDT)
|
||||
*/
|
||||
#define ACPI_RSDT_SIGNATURE 0x54445352 // RSDT
|
||||
struct AcpiRsdtDescriptorRev1
|
||||
{
|
||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||
uint32_t table_offset_entry[0]; /* Array of pointers to other */
|
||||
/* ACPI tables */
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
|
||||
|
||||
/*
|
||||
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
|
||||
*/
|
||||
#define ACPI_FACS_SIGNATURE 0x53434146 // FACS
|
||||
struct AcpiFacsDescriptorRev1
|
||||
{
|
||||
uint32_t signature; /* ACPI Signature */
|
||||
uint32_t length; /* Length of structure, in bytes */
|
||||
uint32_t hardware_signature; /* Hardware configuration signature */
|
||||
uint32_t firmware_waking_vector; /* ACPI OS waking vector */
|
||||
uint32_t global_lock; /* Global Lock */
|
||||
uint32_t flags;
|
||||
uint8_t resverved3 [40]; /* Reserved - must be zero */
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
|
||||
|
||||
/*
|
||||
* Differentiated System Description Table (DSDT)
|
||||
*/
|
||||
#define ACPI_DSDT_SIGNATURE 0x54445344 // DSDT
|
||||
|
||||
/*
|
||||
* MADT values and structures
|
||||
*/
|
||||
|
||||
/* Values for MADT PCATCompat */
|
||||
|
||||
#define ACPI_DUAL_PIC 0
|
||||
#define ACPI_MULTIPLE_APIC 1
|
||||
|
||||
/* Master MADT */
|
||||
|
||||
#define ACPI_APIC_SIGNATURE 0x43495041 // APIC
|
||||
struct AcpiMultipleApicTable
|
||||
{
|
||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||
uint32_t local_apic_address; /* Physical address of local APIC */
|
||||
uint32_t flags;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
|
||||
|
||||
/* Values for Type in APIC sub-headers */
|
||||
|
||||
#define ACPI_APIC_PROCESSOR 0
|
||||
#define ACPI_APIC_IO 1
|
||||
#define ACPI_APIC_XRUPT_OVERRIDE 2
|
||||
#define ACPI_APIC_NMI 3
|
||||
#define ACPI_APIC_LOCAL_NMI 4
|
||||
#define ACPI_APIC_ADDRESS_OVERRIDE 5
|
||||
#define ACPI_APIC_IO_SAPIC 6
|
||||
#define ACPI_APIC_LOCAL_SAPIC 7
|
||||
#define ACPI_APIC_XRUPT_SOURCE 8
|
||||
#define ACPI_APIC_RESERVED 9 /* 9 and greater are reserved */
|
||||
|
||||
/*
|
||||
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
|
||||
*/
|
||||
#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
|
||||
uint8_t type; \
|
||||
uint8_t length;
|
||||
|
||||
/* Sub-structures for MADT */
|
||||
|
||||
struct AcpiMadtProcessorApic
|
||||
{
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t processor_id; /* ACPI processor id */
|
||||
uint8_t local_apic_id; /* Processor's local APIC id */
|
||||
uint32_t flags;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic;
|
||||
|
||||
struct AcpiMadtIoApic
|
||||
{
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t io_apic_id; /* I/O APIC ID */
|
||||
uint8_t reserved; /* Reserved - must be zero */
|
||||
uint32_t address; /* APIC physical address */
|
||||
uint32_t interrupt; /* Global system interrupt where INTI
|
||||
* lines start */
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMadtIoApic AcpiMadtIoApic;
|
||||
|
||||
struct AcpiMadtIntsrcovr {
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t bus;
|
||||
uint8_t source;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr;
|
||||
|
||||
struct AcpiMadtLocalNmi {
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t processor_id; /* ACPI processor id */
|
||||
uint16_t flags; /* MPS INTI flags */
|
||||
uint8_t lint; /* Local APIC LINT# */
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
||||
|
||||
/*
|
||||
* HPET Description Table
|
||||
*/
|
||||
#define ACPI_HPET_SIGNATURE 0x54455048 // HPET
|
||||
struct Acpi20Hpet {
|
||||
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
||||
uint32_t timer_block_id;
|
||||
Acpi20GenericAddress addr;
|
||||
uint8_t hpet_number;
|
||||
uint16_t min_tick;
|
||||
uint8_t page_protect;
|
||||
} QEMU_PACKED;
|
||||
typedef struct Acpi20Hpet Acpi20Hpet;
|
||||
|
||||
/*
|
||||
* SRAT (NUMA topology description) table
|
||||
*/
|
||||
|
||||
#define ACPI_SRAT_SIGNATURE 0x54415253 // SRAT
|
||||
struct AcpiSystemResourceAffinityTable
|
||||
{
|
||||
ACPI_TABLE_HEADER_DEF
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2[2];
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
|
||||
|
||||
#define ACPI_SRAT_PROCESSOR 0
|
||||
#define ACPI_SRAT_MEMORY 1
|
||||
|
||||
struct AcpiSratProcessorAffinity
|
||||
{
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t proximity_lo;
|
||||
uint8_t local_apic_id;
|
||||
uint32_t flags;
|
||||
uint8_t local_sapic_eid;
|
||||
uint8_t proximity_hi[3];
|
||||
uint32_t reserved;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
|
||||
|
||||
struct AcpiSratMemoryAffinity
|
||||
{
|
||||
ACPI_SUB_HEADER_DEF
|
||||
uint8_t proximity[4];
|
||||
uint16_t reserved1;
|
||||
uint64_t base_addr;
|
||||
uint64_t range_length;
|
||||
uint32_t reserved2;
|
||||
uint32_t flags;
|
||||
uint32_t reserved3[2];
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
|
||||
|
||||
/* PCI fw r3.0 MCFG table. */
|
||||
/* Subtable */
|
||||
struct AcpiMcfgAllocation {
|
||||
uint64_t address; /* Base address, processor-relative */
|
||||
uint16_t pci_segment; /* PCI segment group number */
|
||||
uint8_t start_bus_number; /* Starting PCI Bus number */
|
||||
uint8_t end_bus_number; /* Final PCI Bus number */
|
||||
uint32_t reserved;
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
|
||||
|
||||
#define ACPI_MCFG_SIGNATURE 0x4746434d // MCFG
|
||||
|
||||
/* Reserved signature: ignored by OSPM */
|
||||
#define ACPI_RSRV_SIGNATURE 0x554d4551 // QEMU
|
||||
|
||||
struct AcpiTableMcfg {
|
||||
ACPI_TABLE_HEADER_DEF;
|
||||
uint8_t reserved[8];
|
||||
AcpiMcfgAllocation allocation[0];
|
||||
} QEMU_PACKED;
|
||||
typedef struct AcpiTableMcfg AcpiTableMcfg;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
* CPU hotplug
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB) {
|
||||
/* Objects filled in by run-time generated SSDT */
|
||||
External(NTFY, MethodObj)
|
||||
External(CPON, PkgObj)
|
||||
|
||||
/* Methods called by run-time generated SSDT Processor objects */
|
||||
Method(CPMA, 1, NotSerialized) {
|
||||
// _MAT method - create an madt apic buffer
|
||||
// Arg0 = Processor ID = Local APIC ID
|
||||
// Local0 = CPON flag for this cpu
|
||||
Store(DerefOf(Index(CPON, Arg0)), Local0)
|
||||
// Local1 = Buffer (in madt apic form) to return
|
||||
Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
|
||||
// Update the processor id, lapic id, and enable/disable status
|
||||
Store(Arg0, Index(Local1, 2))
|
||||
Store(Arg0, Index(Local1, 3))
|
||||
Store(Local0, Index(Local1, 4))
|
||||
Return (Local1)
|
||||
}
|
||||
Method(CPST, 1, NotSerialized) {
|
||||
// _STA method - return ON status of cpu
|
||||
// Arg0 = Processor ID = Local APIC ID
|
||||
// Local0 = CPON flag for this cpu
|
||||
Store(DerefOf(Index(CPON, Arg0)), Local0)
|
||||
If (Local0) {
|
||||
Return (0xF)
|
||||
} Else {
|
||||
Return (0x0)
|
||||
}
|
||||
}
|
||||
Method(CPEJ, 2, NotSerialized) {
|
||||
// _EJ0 method - eject callback
|
||||
Sleep(200)
|
||||
}
|
||||
|
||||
/* CPU hotplug notify method */
|
||||
OperationRegion(PRST, SystemIO, 0xaf00, 32)
|
||||
Field(PRST, ByteAcc, NoLock, Preserve) {
|
||||
PRS, 256
|
||||
}
|
||||
Method(PRSC, 0) {
|
||||
// Local5 = active cpu bitmap
|
||||
Store(PRS, Local5)
|
||||
// Local2 = last read byte from bitmap
|
||||
Store(Zero, Local2)
|
||||
// Local0 = Processor ID / APIC ID iterator
|
||||
Store(Zero, Local0)
|
||||
While (LLess(Local0, SizeOf(CPON))) {
|
||||
// Local1 = CPON flag for this cpu
|
||||
Store(DerefOf(Index(CPON, Local0)), Local1)
|
||||
If (And(Local0, 0x07)) {
|
||||
// Shift down previously read bitmap byte
|
||||
ShiftRight(Local2, 1, Local2)
|
||||
} Else {
|
||||
// Read next byte from cpu bitmap
|
||||
Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
|
||||
}
|
||||
// Local3 = active state for this cpu
|
||||
Store(And(Local2, 1), Local3)
|
||||
|
||||
If (LNotEqual(Local1, Local3)) {
|
||||
// State change - update CPON with new state
|
||||
Store(Local3, Index(CPON, Local0))
|
||||
// Do CPU notify
|
||||
If (LEqual(Local3, 1)) {
|
||||
NTFY(Local0, 1)
|
||||
} Else {
|
||||
NTFY(Local0, 3)
|
||||
}
|
||||
}
|
||||
Increment(Local0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
* Debugging
|
||||
****************************************************************/
|
||||
|
||||
Scope(\) {
|
||||
/* Debug Output */
|
||||
OperationRegion(DBG, SystemIO, 0x0402, 0x01)
|
||||
Field(DBG, ByteAcc, NoLock, Preserve) {
|
||||
DBGB, 8,
|
||||
}
|
||||
|
||||
/* Debug method - use this method to send output to the QEMU
|
||||
* BIOS debug port. This method handles strings, integers,
|
||||
* and buffers. For example: DBUG("abc") DBUG(0x123) */
|
||||
Method(DBUG, 1) {
|
||||
ToHexString(Arg0, Local0)
|
||||
ToBuffer(Local0, Local0)
|
||||
Subtract(SizeOf(Local0), 1, Local1)
|
||||
Store(Zero, Local2)
|
||||
While (LLess(Local2, Local1)) {
|
||||
Store(DerefOf(Index(Local0, Local2)), DBGB)
|
||||
Increment(Local2)
|
||||
}
|
||||
Store(0x0A, DBGB)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
* HPET
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB) {
|
||||
Device(HPET) {
|
||||
Name(_HID, EISAID("PNP0103"))
|
||||
Name(_UID, 0)
|
||||
OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
|
||||
Field(HPTM, DWordAcc, Lock, Preserve) {
|
||||
VEND, 32,
|
||||
PRD, 32,
|
||||
}
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(VEND, Local0)
|
||||
Store(PRD, Local1)
|
||||
ShiftRight(Local0, 16, Local0)
|
||||
If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
|
||||
Return (0x0)
|
||||
}
|
||||
If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
|
||||
Return (0x0)
|
||||
}
|
||||
Return (0x0F)
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
|
||||
IRQNoFlags() {2, 8}
|
||||
#endif
|
||||
Memory32Fixed(ReadOnly,
|
||||
0xFED00000, // Address Base
|
||||
0x00000400, // Address Length
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Common legacy ISA style devices. */
|
||||
Scope(\_SB.PCI0.ISA) {
|
||||
|
||||
Device(RTC) {
|
||||
Name(_HID, EisaId("PNP0B00"))
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
|
||||
IRQNoFlags() { 8 }
|
||||
IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
|
||||
})
|
||||
}
|
||||
|
||||
Device(KBD) {
|
||||
Name(_HID, EisaId("PNP0303"))
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Return (0x0f)
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
|
||||
IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
|
||||
IRQNoFlags() { 1 }
|
||||
})
|
||||
}
|
||||
|
||||
Device(MOU) {
|
||||
Name(_HID, EisaId("PNP0F13"))
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Return (0x0f)
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IRQNoFlags() { 12 }
|
||||
})
|
||||
}
|
||||
|
||||
Device(FDC0) {
|
||||
Name(_HID, EisaId("PNP0700"))
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(FDEN, Local0)
|
||||
If (LEqual(Local0, 0)) {
|
||||
Return (0x00)
|
||||
} Else {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
|
||||
IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
|
||||
IRQNoFlags() { 6 }
|
||||
DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
|
||||
})
|
||||
}
|
||||
|
||||
Device(LPT) {
|
||||
Name(_HID, EisaId("PNP0400"))
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(LPEN, Local0)
|
||||
If (LEqual(Local0, 0)) {
|
||||
Return (0x00)
|
||||
} Else {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
|
||||
IRQNoFlags() { 7 }
|
||||
})
|
||||
}
|
||||
|
||||
Device(COM1) {
|
||||
Name(_HID, EisaId("PNP0501"))
|
||||
Name(_UID, 0x01)
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(CAEN, Local0)
|
||||
If (LEqual(Local0, 0)) {
|
||||
Return (0x00)
|
||||
} Else {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
|
||||
IRQNoFlags() { 4 }
|
||||
})
|
||||
}
|
||||
|
||||
Device(COM2) {
|
||||
Name(_HID, EisaId("PNP0501"))
|
||||
Name(_UID, 0x02)
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(CBEN, Local0)
|
||||
If (LEqual(Local0, 0)) {
|
||||
Return (0x00)
|
||||
} Else {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
|
||||
IRQNoFlags() { 3 }
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* PCI CRS (current resources) definition. */
|
||||
Scope(\_SB.PCI0) {
|
||||
|
||||
Name(CRES, ResourceTemplate() {
|
||||
WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0000, // Address Range Minimum
|
||||
0x00FF, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0x0100, // Address Length
|
||||
,, )
|
||||
IO(Decode16,
|
||||
0x0CF8, // Address Range Minimum
|
||||
0x0CF8, // Address Range Maximum
|
||||
0x01, // Address Alignment
|
||||
0x08, // Address Length
|
||||
)
|
||||
WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0000, // Address Range Minimum
|
||||
0x0CF7, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0x0CF8, // Address Length
|
||||
,, , TypeStatic)
|
||||
WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0D00, // Address Range Minimum
|
||||
0xFFFF, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0xF300, // Address Length
|
||||
,, , TypeStatic)
|
||||
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x000A0000, // Address Range Minimum
|
||||
0x000BFFFF, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x00020000, // Address Length
|
||||
,, , AddressRangeMemory, TypeStatic)
|
||||
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0xE0000000, // Address Range Minimum
|
||||
0xFEBFFFFF, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x1EC00000, // Address Length
|
||||
,, PW32, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
|
||||
Name(CR64, ResourceTemplate() {
|
||||
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x8000000000, // Address Range Minimum
|
||||
0xFFFFFFFFFF, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x8000000000, // Address Length
|
||||
,, PW64, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
|
||||
Method(_CRS, 0) {
|
||||
/* Fields provided by dynamically created ssdt */
|
||||
External(P0S, IntObj)
|
||||
External(P0E, IntObj)
|
||||
External(P1V, IntObj)
|
||||
External(P1S, BuffObj)
|
||||
External(P1E, BuffObj)
|
||||
External(P1L, BuffObj)
|
||||
|
||||
/* fixup 32bit pci io window */
|
||||
CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
|
||||
CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
|
||||
CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
|
||||
Store(P0S, PS32)
|
||||
Store(P0E, PE32)
|
||||
Store(Add(Subtract(P0E, P0S), 1), PL32)
|
||||
|
||||
If (LEqual(P1V, Zero)) {
|
||||
Return (CRES)
|
||||
}
|
||||
|
||||
/* fixup 64bit pci io window */
|
||||
CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
|
||||
CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
|
||||
CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
|
||||
Store(P1S, PS64)
|
||||
Store(P1E, PE64)
|
||||
Store(P1L, PL64)
|
||||
/* add window and return result */
|
||||
ConcatenateResTemplate(CRES, CR64, Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* Bochs/QEMU ACPI DSDT ASL definition
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE AcpiDsdtAmlCode
|
||||
|
||||
DefinitionBlock (
|
||||
"acpi-dsdt.aml", // Output Filename
|
||||
"DSDT", // Signature
|
||||
0x01, // DSDT Compliance Revision
|
||||
"BXPC", // OEMID
|
||||
"BXDSDT", // TABLE ID
|
||||
0x1 // OEM Revision
|
||||
)
|
||||
{
|
||||
|
||||
#include "acpi-dsdt-dbug.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PCI Bus definition
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB) {
|
||||
Device(PCI0) {
|
||||
Name(_HID, EisaId("PNP0A03"))
|
||||
Name(_ADR, 0x00)
|
||||
Name(_UID, 1)
|
||||
}
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-pci-crs.dsl"
|
||||
#include "acpi-dsdt-hpet.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* VGA
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(VGA) {
|
||||
Name(_ADR, 0x00020000)
|
||||
OperationRegion(PCIC, PCI_Config, Zero, 0x4)
|
||||
Field(PCIC, DWordAcc, NoLock, Preserve) {
|
||||
VEND, 32
|
||||
}
|
||||
Method(_S1D, 0, NotSerialized) {
|
||||
Return (0x00)
|
||||
}
|
||||
Method(_S2D, 0, NotSerialized) {
|
||||
Return (0x00)
|
||||
}
|
||||
Method(_S3D, 0, NotSerialized) {
|
||||
If (LEqual(VEND, 0x1001b36)) {
|
||||
Return (0x03) // QXL
|
||||
} Else {
|
||||
Return (0x00)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PIIX4 PM
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(PX13) {
|
||||
Name(_ADR, 0x00010003)
|
||||
OperationRegion(P13C, PCI_Config, 0x00, 0xff)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PIIX3 ISA bridge
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(ISA) {
|
||||
Name(_ADR, 0x00010000)
|
||||
|
||||
/* PIIX PCI to ISA irq remapping */
|
||||
OperationRegion(P40C, PCI_Config, 0x60, 0x04)
|
||||
|
||||
/* enable bits */
|
||||
Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
|
||||
Offset(0x5f),
|
||||
, 7,
|
||||
LPEN, 1, // LPT
|
||||
Offset(0x67),
|
||||
, 3,
|
||||
CAEN, 1, // COM1
|
||||
, 3,
|
||||
CBEN, 1, // COM2
|
||||
}
|
||||
Name(FDEN, 1)
|
||||
}
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-isa.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PCI hotplug
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
OperationRegion(PCST, SystemIO, 0xae00, 0x08)
|
||||
Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
|
||||
PCIU, 32,
|
||||
PCID, 32,
|
||||
}
|
||||
|
||||
OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
|
||||
Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
|
||||
B0EJ, 32,
|
||||
}
|
||||
|
||||
/* Methods called by bulk generated PCI devices below */
|
||||
|
||||
/* Methods called by hotplug devices */
|
||||
Method(PCEJ, 1, NotSerialized) {
|
||||
// _EJ0 method - eject callback
|
||||
Store(ShiftLeft(1, Arg0), B0EJ)
|
||||
Return (0x0)
|
||||
}
|
||||
|
||||
/* Hotplug notification method supplied by SSDT */
|
||||
External(\_SB.PCI0.PCNT, MethodObj)
|
||||
|
||||
/* PCI hotplug notify method */
|
||||
Method(PCNF, 0) {
|
||||
// Local0 = iterator
|
||||
Store(Zero, Local0)
|
||||
While (LLess(Local0, 31)) {
|
||||
Increment(Local0)
|
||||
If (And(PCIU, ShiftLeft(1, Local0))) {
|
||||
PCNT(Local0, 1)
|
||||
}
|
||||
If (And(PCID, ShiftLeft(1, Local0))) {
|
||||
PCNT(Local0, 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PCI IRQs
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB) {
|
||||
Scope(PCI0) {
|
||||
Name(_PRT, Package() {
|
||||
/* PCI IRQ routing table, example from ACPI 2.0a specification,
|
||||
section 6.2.8.1 */
|
||||
/* Note: we provide the same info as the PCI routing
|
||||
table of the Bochs BIOS */
|
||||
|
||||
#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
|
||||
Package() { nr##ffff, 0, lnk0, 0 }, \
|
||||
Package() { nr##ffff, 1, lnk1, 0 }, \
|
||||
Package() { nr##ffff, 2, lnk2, 0 }, \
|
||||
Package() { nr##ffff, 3, lnk3, 0 }
|
||||
|
||||
#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
|
||||
#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
|
||||
#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
|
||||
#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
|
||||
|
||||
prt_slot0(0x0000),
|
||||
/* Device 1 is power mgmt device, and can only use irq 9 */
|
||||
prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
|
||||
prt_slot2(0x0002),
|
||||
prt_slot3(0x0003),
|
||||
prt_slot0(0x0004),
|
||||
prt_slot1(0x0005),
|
||||
prt_slot2(0x0006),
|
||||
prt_slot3(0x0007),
|
||||
prt_slot0(0x0008),
|
||||
prt_slot1(0x0009),
|
||||
prt_slot2(0x000a),
|
||||
prt_slot3(0x000b),
|
||||
prt_slot0(0x000c),
|
||||
prt_slot1(0x000d),
|
||||
prt_slot2(0x000e),
|
||||
prt_slot3(0x000f),
|
||||
prt_slot0(0x0010),
|
||||
prt_slot1(0x0011),
|
||||
prt_slot2(0x0012),
|
||||
prt_slot3(0x0013),
|
||||
prt_slot0(0x0014),
|
||||
prt_slot1(0x0015),
|
||||
prt_slot2(0x0016),
|
||||
prt_slot3(0x0017),
|
||||
prt_slot0(0x0018),
|
||||
prt_slot1(0x0019),
|
||||
prt_slot2(0x001a),
|
||||
prt_slot3(0x001b),
|
||||
prt_slot0(0x001c),
|
||||
prt_slot1(0x001d),
|
||||
prt_slot2(0x001e),
|
||||
prt_slot3(0x001f),
|
||||
})
|
||||
}
|
||||
|
||||
Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
|
||||
PRQ0, 8,
|
||||
PRQ1, 8,
|
||||
PRQ2, 8,
|
||||
PRQ3, 8
|
||||
}
|
||||
|
||||
Method(IQST, 1, NotSerialized) {
|
||||
// _STA method - get status
|
||||
If (And(0x80, Arg0)) {
|
||||
Return (0x09)
|
||||
}
|
||||
Return (0x0B)
|
||||
}
|
||||
Method(IQCR, 1, NotSerialized) {
|
||||
// _CRS method - get current settings
|
||||
Name(PRR0, ResourceTemplate() {
|
||||
Interrupt(, Level, ActiveHigh, Shared) { 0 }
|
||||
})
|
||||
CreateDWordField(PRR0, 0x05, PRRI)
|
||||
If (LLess(Arg0, 0x80)) {
|
||||
Store(Arg0, PRRI)
|
||||
}
|
||||
Return (PRR0)
|
||||
}
|
||||
|
||||
#define define_link(link, uid, reg) \
|
||||
Device(link) { \
|
||||
Name(_HID, EISAID("PNP0C0F")) \
|
||||
Name(_UID, uid) \
|
||||
Name(_PRS, ResourceTemplate() { \
|
||||
Interrupt(, Level, ActiveHigh, Shared) { \
|
||||
5, 10, 11 \
|
||||
} \
|
||||
}) \
|
||||
Method(_STA, 0, NotSerialized) { \
|
||||
Return (IQST(reg)) \
|
||||
} \
|
||||
Method(_DIS, 0, NotSerialized) { \
|
||||
Or(reg, 0x80, reg) \
|
||||
} \
|
||||
Method(_CRS, 0, NotSerialized) { \
|
||||
Return (IQCR(reg)) \
|
||||
} \
|
||||
Method(_SRS, 1, NotSerialized) { \
|
||||
CreateDWordField(Arg0, 0x05, PRRI) \
|
||||
Store(PRRI, reg) \
|
||||
} \
|
||||
}
|
||||
|
||||
define_link(LNKA, 0, PRQ0)
|
||||
define_link(LNKB, 1, PRQ1)
|
||||
define_link(LNKC, 2, PRQ2)
|
||||
define_link(LNKD, 3, PRQ3)
|
||||
|
||||
Device(LNKS) {
|
||||
Name(_HID, EISAID("PNP0C0F"))
|
||||
Name(_UID, 4)
|
||||
Name(_PRS, ResourceTemplate() {
|
||||
Interrupt(, Level, ActiveHigh, Shared) { 9 }
|
||||
})
|
||||
|
||||
// The SCI cannot be disabled and is always attached to GSI 9,
|
||||
// so these are no-ops. We only need this link to override the
|
||||
// polarity to active high and match the content of the MADT.
|
||||
Method(_STA, 0, NotSerialized) { Return (0x0b) }
|
||||
Method(_DIS, 0, NotSerialized) { }
|
||||
Method(_CRS, 0, NotSerialized) { Return (_PRS) }
|
||||
Method(_SRS, 1, NotSerialized) { }
|
||||
}
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-cpu-hotplug.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* General purpose events
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_GPE) {
|
||||
Name(_HID, "ACPI0006")
|
||||
|
||||
Method(_L00) {
|
||||
}
|
||||
Method(_E01) {
|
||||
// PCI hotplug event
|
||||
\_SB.PCI0.PCNF()
|
||||
}
|
||||
Method(_E02) {
|
||||
// CPU hotplug event
|
||||
\_SB.PRSC()
|
||||
}
|
||||
Method(_L03) {
|
||||
}
|
||||
Method(_L04) {
|
||||
}
|
||||
Method(_L05) {
|
||||
}
|
||||
Method(_L06) {
|
||||
}
|
||||
Method(_L07) {
|
||||
}
|
||||
Method(_L08) {
|
||||
}
|
||||
Method(_L09) {
|
||||
}
|
||||
Method(_L0A) {
|
||||
}
|
||||
Method(_L0B) {
|
||||
}
|
||||
Method(_L0C) {
|
||||
}
|
||||
Method(_L0D) {
|
||||
}
|
||||
Method(_L0E) {
|
||||
}
|
||||
Method(_L0F) {
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,158 @@
|
|||
/* Dynamic linker/loader of ACPI tables
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat Inc
|
||||
*
|
||||
* Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bios-linker-loader.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
|
||||
|
||||
struct BiosLinkerLoaderEntry {
|
||||
uint32_t command;
|
||||
union {
|
||||
/*
|
||||
* COMMAND_ALLOCATE - allocate a table from @alloc.file
|
||||
* subject to @alloc.align alignment (must be power of 2)
|
||||
* and @alloc.zone (can be HIGH or FSEG) requirements.
|
||||
*
|
||||
* Must appear exactly once for each file, and before
|
||||
* this file is referenced by any other command.
|
||||
*/
|
||||
struct {
|
||||
char file[BIOS_LINKER_LOADER_FILESZ];
|
||||
uint32_t align;
|
||||
uint8_t zone;
|
||||
} alloc;
|
||||
|
||||
/*
|
||||
* COMMAND_ADD_POINTER - patch the table (originating from
|
||||
* @dest_file) at @pointer.offset, by adding a pointer to the table
|
||||
* originating from @src_file. 1,2,4 or 8 byte unsigned
|
||||
* addition is used depending on @pointer.size.
|
||||
*/
|
||||
struct {
|
||||
char dest_file[BIOS_LINKER_LOADER_FILESZ];
|
||||
char src_file[BIOS_LINKER_LOADER_FILESZ];
|
||||
uint32_t offset;
|
||||
uint8_t size;
|
||||
} pointer;
|
||||
|
||||
/*
|
||||
* COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by
|
||||
* @cksum_start and @cksum_length fields,
|
||||
* and then add the value at @cksum.offset.
|
||||
* Checksum simply sums -X for each byte X in the range
|
||||
* using 8-bit math.
|
||||
*/
|
||||
struct {
|
||||
char file[BIOS_LINKER_LOADER_FILESZ];
|
||||
uint32_t offset;
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
} cksum;
|
||||
|
||||
/* padding */
|
||||
char pad[124];
|
||||
};
|
||||
} QEMU_PACKED;
|
||||
typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry;
|
||||
|
||||
enum {
|
||||
BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1,
|
||||
BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2,
|
||||
BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
|
||||
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
|
||||
};
|
||||
|
||||
GArray *bios_linker_loader_init(void)
|
||||
{
|
||||
return g_array_new(false, true /* clear */, sizeof(BiosLinkerLoaderEntry));
|
||||
}
|
||||
|
||||
/* Free linker wrapper and return the linker array. */
|
||||
void *bios_linker_loader_cleanup(GArray *linker)
|
||||
{
|
||||
return g_array_free(linker, false);
|
||||
}
|
||||
|
||||
void bios_linker_loader_alloc(GArray *linker,
|
||||
const char *file,
|
||||
uint32_t alloc_align,
|
||||
bool alloc_fseg)
|
||||
{
|
||||
BiosLinkerLoaderEntry entry;
|
||||
|
||||
memset(&entry, 0, sizeof entry);
|
||||
strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
|
||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
|
||||
entry.alloc.align = cpu_to_le32(alloc_align);
|
||||
entry.alloc.zone = cpu_to_le32(alloc_fseg ?
|
||||
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
|
||||
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH);
|
||||
|
||||
/* Alloc entries must come first, so prepend them */
|
||||
g_array_prepend_val(linker, entry);
|
||||
}
|
||||
|
||||
void bios_linker_loader_add_checksum(GArray *linker, const char *file,
|
||||
void *table,
|
||||
void *start, unsigned size,
|
||||
uint8_t *checksum)
|
||||
{
|
||||
BiosLinkerLoaderEntry entry;
|
||||
|
||||
memset(&entry, 0, sizeof entry);
|
||||
strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
|
||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
|
||||
entry.cksum.offset = cpu_to_le32(checksum - (uint8_t *)table);
|
||||
entry.cksum.start = cpu_to_le32((uint8_t *)start - (uint8_t *)table);
|
||||
entry.cksum.length = cpu_to_le32(size);
|
||||
|
||||
g_array_append_val(linker, entry);
|
||||
}
|
||||
|
||||
void bios_linker_loader_add_pointer(GArray *linker,
|
||||
const char *dest_file,
|
||||
const char *src_file,
|
||||
GArray *table, void *pointer,
|
||||
uint8_t pointer_size)
|
||||
{
|
||||
BiosLinkerLoaderEntry entry;
|
||||
|
||||
memset(&entry, 0, sizeof entry);
|
||||
strncpy(entry.pointer.dest_file, dest_file,
|
||||
sizeof entry.pointer.dest_file - 1);
|
||||
strncpy(entry.pointer.src_file, src_file,
|
||||
sizeof entry.pointer.src_file - 1);
|
||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
|
||||
entry.pointer.offset = cpu_to_le32((gchar *)pointer - table->data);
|
||||
entry.pointer.size = pointer_size;
|
||||
assert(pointer_size == 1 || pointer_size == 2 ||
|
||||
pointer_size == 4 || pointer_size == 8);
|
||||
|
||||
g_array_append_val(linker, entry);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef BIOS_LINKER_LOADER_H
|
||||
#define BIOS_LINKER_LOADER_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
GArray *bios_linker_loader_init(void);
|
||||
|
||||
void bios_linker_loader_alloc(GArray *linker,
|
||||
const char *file,
|
||||
uint32_t alloc_align,
|
||||
bool alloc_fseg);
|
||||
|
||||
void bios_linker_loader_add_checksum(GArray *linker, const char *file,
|
||||
void *table,
|
||||
void *start, unsigned size,
|
||||
uint8_t *checksum);
|
||||
|
||||
void bios_linker_loader_add_pointer(GArray *linker,
|
||||
const char *dest_file,
|
||||
const char *src_file,
|
||||
GArray *table, void *pointer,
|
||||
uint8_t pointer_size);
|
||||
|
||||
void *bios_linker_loader_cleanup(GArray *linker);
|
||||
#endif
|
25
hw/i386/pc.c
25
hw/i386/pc.c
|
@ -56,6 +56,7 @@
|
|||
#include "hw/cpu/icc_bus.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "acpi-build.h"
|
||||
|
||||
/* debug PC/ISA interrupts */
|
||||
//#define DEBUG_IRQ
|
||||
|
@ -1040,6 +1041,7 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data)
|
|||
PcGuestInfoState,
|
||||
machine_done);
|
||||
pc_fw_cfg_guest_info(&guest_info_state->info);
|
||||
acpi_setup(&guest_info_state->info);
|
||||
}
|
||||
|
||||
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
|
||||
|
@ -1047,6 +1049,27 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
|
|||
{
|
||||
PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
|
||||
PcGuestInfo *guest_info = &guest_info_state->info;
|
||||
int i, j;
|
||||
|
||||
guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
|
||||
guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
|
||||
guest_info->apic_xrupt_override = kvm_allows_irq0_override();
|
||||
guest_info->numa_nodes = nb_numa_nodes;
|
||||
guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes *
|
||||
sizeof *guest_info->node_mem);
|
||||
guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit *
|
||||
sizeof *guest_info->node_cpu);
|
||||
|
||||
for (i = 0; i < max_cpus; i++) {
|
||||
unsigned int apic_id = x86_cpu_apic_id_from_index(i);
|
||||
assert(apic_id < guest_info->apic_id_limit);
|
||||
for (j = 0; j < nb_numa_nodes; j++) {
|
||||
if (test_bit(i, node_cpumask[j])) {
|
||||
guest_info->node_cpu[apic_id] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guest_info_state->machine_done.notify = pc_guest_info_machine_done;
|
||||
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
|
||||
|
@ -1093,7 +1116,7 @@ void pc_acpi_init(const char *default_dsdt)
|
|||
opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
|
||||
g_assert(opts != NULL);
|
||||
|
||||
acpi_table_add(opts, &err);
|
||||
acpi_table_add_builtin(opts, &err);
|
||||
if (err) {
|
||||
error_report("WARNING: failed to load %s: %s", filename,
|
||||
error_get_pretty(err));
|
||||
|
|
|
@ -59,6 +59,7 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
|
|||
|
||||
static bool has_pvpanic;
|
||||
static bool has_pci_info = true;
|
||||
static bool has_acpi_build = true;
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static void pc_init1(QEMUMachineInitArgs *args,
|
||||
|
@ -122,6 +123,9 @@ static void pc_init1(QEMUMachineInitArgs *args,
|
|||
}
|
||||
|
||||
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
|
||||
|
||||
guest_info->has_acpi_build = has_acpi_build;
|
||||
|
||||
guest_info->has_pci_info = has_pci_info;
|
||||
guest_info->isapc_ram_fw = !pci_enabled;
|
||||
|
||||
|
@ -240,6 +244,7 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
|||
{
|
||||
has_pci_info = false;
|
||||
rom_file_in_ram = false;
|
||||
has_acpi_build = false;
|
||||
}
|
||||
|
||||
static void pc_compat_1_5(QEMUMachineInitArgs *args)
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
static bool has_pvpanic;
|
||||
static bool has_pci_info = true;
|
||||
static bool has_acpi_build = true;
|
||||
|
||||
/* PC hardware initialisation */
|
||||
static void pc_q35_init(QEMUMachineInitArgs *args)
|
||||
|
@ -111,6 +112,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
|
|||
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
|
||||
guest_info->has_pci_info = has_pci_info;
|
||||
guest_info->isapc_ram_fw = false;
|
||||
guest_info->has_acpi_build = has_acpi_build;
|
||||
|
||||
/* allocate ram and load rom/bios */
|
||||
if (!xen_enabled()) {
|
||||
|
@ -224,6 +226,7 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args)
|
|||
{
|
||||
has_pci_info = false;
|
||||
rom_file_in_ram = false;
|
||||
has_acpi_build = false;
|
||||
}
|
||||
|
||||
static void pc_compat_1_5(QEMUMachineInitArgs *args)
|
||||
|
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Bochs/QEMU ACPI DSDT ASL definition
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2010 Isaku Yamahata
|
||||
* yamahata at valinux co jp
|
||||
* Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode
|
||||
|
||||
DefinitionBlock (
|
||||
"q35-acpi-dsdt.aml",// Output Filename
|
||||
"DSDT", // Signature
|
||||
0x01, // DSDT Compliance Revision
|
||||
"BXPC", // OEMID
|
||||
"BXDSDT", // TABLE ID
|
||||
0x2 // OEM Revision
|
||||
)
|
||||
{
|
||||
|
||||
#include "acpi-dsdt-dbug.dsl"
|
||||
|
||||
Scope(\_SB) {
|
||||
OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
|
||||
OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
|
||||
Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
|
||||
PCIB, 8,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PCI Bus definition
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB) {
|
||||
Device(PCI0) {
|
||||
Name(_HID, EisaId("PNP0A08"))
|
||||
Name(_CID, EisaId("PNP0A03"))
|
||||
Name(_ADR, 0x00)
|
||||
Name(_UID, 1)
|
||||
|
||||
// _OSC: based on sample of ACPI3.0b spec
|
||||
Name(SUPP, 0) // PCI _OSC Support Field value
|
||||
Name(CTRL, 0) // PCI _OSC Control Field value
|
||||
Method(_OSC, 4) {
|
||||
// Create DWORD-addressable fields from the Capabilities Buffer
|
||||
CreateDWordField(Arg3, 0, CDW1)
|
||||
|
||||
// Check for proper UUID
|
||||
If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
|
||||
// Create DWORD-addressable fields from the Capabilities Buffer
|
||||
CreateDWordField(Arg3, 4, CDW2)
|
||||
CreateDWordField(Arg3, 8, CDW3)
|
||||
|
||||
// Save Capabilities DWORD2 & 3
|
||||
Store(CDW2, SUPP)
|
||||
Store(CDW3, CTRL)
|
||||
|
||||
// Always allow native PME, AER (no dependencies)
|
||||
// Never allow SHPC (no SHPC controller in this system)
|
||||
And(CTRL, 0x1D, CTRL)
|
||||
|
||||
#if 0 // For now, nothing to do
|
||||
If (Not(And(CDW1, 1))) { // Query flag clear?
|
||||
// Disable GPEs for features granted native control.
|
||||
If (And(CTRL, 0x01)) { // Hot plug control granted?
|
||||
Store(0, HPCE) // clear the hot plug SCI enable bit
|
||||
Store(1, HPCS) // clear the hot plug SCI status bit
|
||||
}
|
||||
If (And(CTRL, 0x04)) { // PME control granted?
|
||||
Store(0, PMCE) // clear the PME SCI enable bit
|
||||
Store(1, PMCS) // clear the PME SCI status bit
|
||||
}
|
||||
If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
|
||||
// Set status to not restore PCI Express cap structure
|
||||
// upon resume from S3
|
||||
Store(1, S3CR)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
If (LNotEqual(Arg1, One)) {
|
||||
// Unknown revision
|
||||
Or(CDW1, 0x08, CDW1)
|
||||
}
|
||||
If (LNotEqual(CDW3, CTRL)) {
|
||||
// Capabilities bits were masked
|
||||
Or(CDW1, 0x10, CDW1)
|
||||
}
|
||||
// Update DWORD3 in the buffer
|
||||
Store(CTRL, CDW3)
|
||||
} Else {
|
||||
Or(CDW1, 4, CDW1) // Unrecognized UUID
|
||||
}
|
||||
Return (Arg3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-pci-crs.dsl"
|
||||
#include "acpi-dsdt-hpet.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* VGA
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
Device(VGA) {
|
||||
Name(_ADR, 0x00010000)
|
||||
Method(_S1D, 0, NotSerialized) {
|
||||
Return (0x00)
|
||||
}
|
||||
Method(_S2D, 0, NotSerialized) {
|
||||
Return (0x00)
|
||||
}
|
||||
Method(_S3D, 0, NotSerialized) {
|
||||
Return (0x00)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* LPC ISA bridge
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
/* PCI D31:f0 LPC ISA bridge */
|
||||
Device(ISA) {
|
||||
/* PCI D31:f0 */
|
||||
Name(_ADR, 0x001f0000)
|
||||
|
||||
/* ICH9 PCI to ISA irq remapping */
|
||||
OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
|
||||
|
||||
OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
|
||||
Field(LPCD, AnyAcc, NoLock, Preserve) {
|
||||
COMA, 3,
|
||||
, 1,
|
||||
COMB, 3,
|
||||
|
||||
Offset(0x01),
|
||||
LPTD, 2,
|
||||
, 2,
|
||||
FDCD, 2
|
||||
}
|
||||
OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
|
||||
Field(LPCE, AnyAcc, NoLock, Preserve) {
|
||||
CAEN, 1,
|
||||
CBEN, 1,
|
||||
LPEN, 1,
|
||||
FDEN, 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-isa.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* PCI IRQs
|
||||
****************************************************************/
|
||||
|
||||
/* Zero => PIC mode, One => APIC Mode */
|
||||
Name(\PICF, Zero)
|
||||
Method(\_PIC, 1, NotSerialized) {
|
||||
Store(Arg0, \PICF)
|
||||
}
|
||||
|
||||
Scope(\_SB) {
|
||||
Scope(PCI0) {
|
||||
#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \
|
||||
Package() { nr##ffff, 0, lnk0, 0 }, \
|
||||
Package() { nr##ffff, 1, lnk1, 0 }, \
|
||||
Package() { nr##ffff, 2, lnk2, 0 }, \
|
||||
Package() { nr##ffff, 3, lnk3, 0 }
|
||||
|
||||
#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
|
||||
#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
|
||||
#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
|
||||
#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
|
||||
|
||||
#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
|
||||
#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
|
||||
#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
|
||||
#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
|
||||
|
||||
Name(PRTP, package() {
|
||||
prt_slot_lnkE(0x0000),
|
||||
prt_slot_lnkF(0x0001),
|
||||
prt_slot_lnkG(0x0002),
|
||||
prt_slot_lnkH(0x0003),
|
||||
prt_slot_lnkE(0x0004),
|
||||
prt_slot_lnkF(0x0005),
|
||||
prt_slot_lnkG(0x0006),
|
||||
prt_slot_lnkH(0x0007),
|
||||
prt_slot_lnkE(0x0008),
|
||||
prt_slot_lnkF(0x0009),
|
||||
prt_slot_lnkG(0x000a),
|
||||
prt_slot_lnkH(0x000b),
|
||||
prt_slot_lnkE(0x000c),
|
||||
prt_slot_lnkF(0x000d),
|
||||
prt_slot_lnkG(0x000e),
|
||||
prt_slot_lnkH(0x000f),
|
||||
prt_slot_lnkE(0x0010),
|
||||
prt_slot_lnkF(0x0011),
|
||||
prt_slot_lnkG(0x0012),
|
||||
prt_slot_lnkH(0x0013),
|
||||
prt_slot_lnkE(0x0014),
|
||||
prt_slot_lnkF(0x0015),
|
||||
prt_slot_lnkG(0x0016),
|
||||
prt_slot_lnkH(0x0017),
|
||||
prt_slot_lnkE(0x0018),
|
||||
|
||||
/* INTA -> PIRQA for slot 25 - 31
|
||||
see the default value of D<N>IR */
|
||||
prt_slot_lnkA(0x0019),
|
||||
prt_slot_lnkA(0x001a),
|
||||
prt_slot_lnkA(0x001b),
|
||||
prt_slot_lnkA(0x001c),
|
||||
prt_slot_lnkA(0x001d),
|
||||
|
||||
/* PCIe->PCI bridge. use PIRQ[E-H] */
|
||||
prt_slot_lnkE(0x001e),
|
||||
|
||||
prt_slot_lnkA(0x001f)
|
||||
})
|
||||
|
||||
#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \
|
||||
Package() { nr##ffff, 0, gsi0, 0 }, \
|
||||
Package() { nr##ffff, 1, gsi1, 0 }, \
|
||||
Package() { nr##ffff, 2, gsi2, 0 }, \
|
||||
Package() { nr##ffff, 3, gsi3, 0 }
|
||||
|
||||
#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
|
||||
#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
|
||||
#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
|
||||
#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
|
||||
|
||||
#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
|
||||
#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
|
||||
#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
|
||||
#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
|
||||
|
||||
Name(PRTA, package() {
|
||||
prt_slot_gsiE(0x0000),
|
||||
prt_slot_gsiF(0x0001),
|
||||
prt_slot_gsiG(0x0002),
|
||||
prt_slot_gsiH(0x0003),
|
||||
prt_slot_gsiE(0x0004),
|
||||
prt_slot_gsiF(0x0005),
|
||||
prt_slot_gsiG(0x0006),
|
||||
prt_slot_gsiH(0x0007),
|
||||
prt_slot_gsiE(0x0008),
|
||||
prt_slot_gsiF(0x0009),
|
||||
prt_slot_gsiG(0x000a),
|
||||
prt_slot_gsiH(0x000b),
|
||||
prt_slot_gsiE(0x000c),
|
||||
prt_slot_gsiF(0x000d),
|
||||
prt_slot_gsiG(0x000e),
|
||||
prt_slot_gsiH(0x000f),
|
||||
prt_slot_gsiE(0x0010),
|
||||
prt_slot_gsiF(0x0011),
|
||||
prt_slot_gsiG(0x0012),
|
||||
prt_slot_gsiH(0x0013),
|
||||
prt_slot_gsiE(0x0014),
|
||||
prt_slot_gsiF(0x0015),
|
||||
prt_slot_gsiG(0x0016),
|
||||
prt_slot_gsiH(0x0017),
|
||||
prt_slot_gsiE(0x0018),
|
||||
|
||||
/* INTA -> PIRQA for slot 25 - 31, but 30
|
||||
see the default value of D<N>IR */
|
||||
prt_slot_gsiA(0x0019),
|
||||
prt_slot_gsiA(0x001a),
|
||||
prt_slot_gsiA(0x001b),
|
||||
prt_slot_gsiA(0x001c),
|
||||
prt_slot_gsiA(0x001d),
|
||||
|
||||
/* PCIe->PCI bridge. use PIRQ[E-H] */
|
||||
prt_slot_gsiE(0x001e),
|
||||
|
||||
prt_slot_gsiA(0x001f)
|
||||
})
|
||||
|
||||
Method(_PRT, 0, NotSerialized) {
|
||||
/* PCI IRQ routing table, example from ACPI 2.0a specification,
|
||||
section 6.2.8.1 */
|
||||
/* Note: we provide the same info as the PCI routing
|
||||
table of the Bochs BIOS */
|
||||
If (LEqual(\PICF, Zero)) {
|
||||
Return (PRTP)
|
||||
} Else {
|
||||
Return (PRTA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
|
||||
PRQA, 8,
|
||||
PRQB, 8,
|
||||
PRQC, 8,
|
||||
PRQD, 8,
|
||||
|
||||
Offset(0x08),
|
||||
PRQE, 8,
|
||||
PRQF, 8,
|
||||
PRQG, 8,
|
||||
PRQH, 8
|
||||
}
|
||||
|
||||
Method(IQST, 1, NotSerialized) {
|
||||
// _STA method - get status
|
||||
If (And(0x80, Arg0)) {
|
||||
Return (0x09)
|
||||
}
|
||||
Return (0x0B)
|
||||
}
|
||||
Method(IQCR, 1, NotSerialized) {
|
||||
// _CRS method - get current settings
|
||||
Name(PRR0, ResourceTemplate() {
|
||||
Interrupt(, Level, ActiveHigh, Shared) { 0 }
|
||||
})
|
||||
CreateDWordField(PRR0, 0x05, PRRI)
|
||||
Store(And(Arg0, 0x0F), PRRI)
|
||||
Return (PRR0)
|
||||
}
|
||||
|
||||
#define define_link(link, uid, reg) \
|
||||
Device(link) { \
|
||||
Name(_HID, EISAID("PNP0C0F")) \
|
||||
Name(_UID, uid) \
|
||||
Name(_PRS, ResourceTemplate() { \
|
||||
Interrupt(, Level, ActiveHigh, Shared) { \
|
||||
5, 10, 11 \
|
||||
} \
|
||||
}) \
|
||||
Method(_STA, 0, NotSerialized) { \
|
||||
Return (IQST(reg)) \
|
||||
} \
|
||||
Method(_DIS, 0, NotSerialized) { \
|
||||
Or(reg, 0x80, reg) \
|
||||
} \
|
||||
Method(_CRS, 0, NotSerialized) { \
|
||||
Return (IQCR(reg)) \
|
||||
} \
|
||||
Method(_SRS, 1, NotSerialized) { \
|
||||
CreateDWordField(Arg0, 0x05, PRRI) \
|
||||
Store(PRRI, reg) \
|
||||
} \
|
||||
}
|
||||
|
||||
define_link(LNKA, 0, PRQA)
|
||||
define_link(LNKB, 1, PRQB)
|
||||
define_link(LNKC, 2, PRQC)
|
||||
define_link(LNKD, 3, PRQD)
|
||||
define_link(LNKE, 4, PRQE)
|
||||
define_link(LNKF, 5, PRQF)
|
||||
define_link(LNKG, 6, PRQG)
|
||||
define_link(LNKH, 7, PRQH)
|
||||
|
||||
#define define_gsi_link(link, uid, gsi) \
|
||||
Device(link) { \
|
||||
Name(_HID, EISAID("PNP0C0F")) \
|
||||
Name(_UID, uid) \
|
||||
Name(_PRS, ResourceTemplate() { \
|
||||
Interrupt(, Level, ActiveHigh, Shared) { \
|
||||
gsi \
|
||||
} \
|
||||
}) \
|
||||
Name(_CRS, ResourceTemplate() { \
|
||||
Interrupt(, Level, ActiveHigh, Shared) { \
|
||||
gsi \
|
||||
} \
|
||||
}) \
|
||||
Method(_SRS, 1, NotSerialized) { \
|
||||
} \
|
||||
}
|
||||
|
||||
define_gsi_link(GSIA, 0, 0x10)
|
||||
define_gsi_link(GSIB, 0, 0x11)
|
||||
define_gsi_link(GSIC, 0, 0x12)
|
||||
define_gsi_link(GSID, 0, 0x13)
|
||||
define_gsi_link(GSIE, 0, 0x14)
|
||||
define_gsi_link(GSIF, 0, 0x15)
|
||||
define_gsi_link(GSIG, 0, 0x16)
|
||||
define_gsi_link(GSIH, 0, 0x17)
|
||||
}
|
||||
|
||||
#include "acpi-dsdt-cpu-hotplug.dsl"
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* General purpose events
|
||||
****************************************************************/
|
||||
|
||||
Scope(\_GPE) {
|
||||
Name(_HID, "ACPI0006")
|
||||
|
||||
Method(_L00) {
|
||||
}
|
||||
Method(_L01) {
|
||||
// CPU hotplug event
|
||||
\_SB.PRSC()
|
||||
}
|
||||
Method(_L02) {
|
||||
}
|
||||
Method(_L03) {
|
||||
}
|
||||
Method(_L04) {
|
||||
}
|
||||
Method(_L05) {
|
||||
}
|
||||
Method(_L06) {
|
||||
}
|
||||
Method(_L07) {
|
||||
}
|
||||
Method(_L08) {
|
||||
}
|
||||
Method(_L09) {
|
||||
}
|
||||
Method(_L0A) {
|
||||
}
|
||||
Method(_L0B) {
|
||||
}
|
||||
Method(_L0C) {
|
||||
}
|
||||
Method(_L0D) {
|
||||
}
|
||||
Method(_L0E) {
|
||||
}
|
||||
Method(_L0F) {
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
|
||||
|
||||
DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
|
||||
{
|
||||
|
||||
/****************************************************************
|
||||
* PCI memory ranges
|
||||
****************************************************************/
|
||||
|
||||
Scope(\) {
|
||||
ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
|
||||
Name(P0S, 0x12345678)
|
||||
ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
|
||||
Name(P0E, 0x12345678)
|
||||
ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
|
||||
Name(P1V, 0x12)
|
||||
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
|
||||
Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
|
||||
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
|
||||
Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
|
||||
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
|
||||
Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Suspend
|
||||
****************************************************************/
|
||||
|
||||
Scope(\) {
|
||||
/*
|
||||
* S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
|
||||
* must match piix4 emulation.
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_NAME_STRING acpi_s3_name
|
||||
Name(_S3, Package(0x04) {
|
||||
One, /* PM1a_CNT.SLP_TYP */
|
||||
One, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
ACPI_EXTRACT_NAME_STRING acpi_s4_name
|
||||
ACPI_EXTRACT_PKG_START acpi_s4_pkg
|
||||
Name(_S4, Package(0x04) {
|
||||
0x2, /* PM1a_CNT.SLP_TYP */
|
||||
0x2, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
Name(_S5, Package(0x04) {
|
||||
Zero, /* PM1a_CNT.SLP_TYP */
|
||||
Zero, /* PM1b_CNT.SLP_TYP */
|
||||
Zero, /* reserved */
|
||||
Zero /* reserved */
|
||||
})
|
||||
}
|
||||
|
||||
External(\_SB.PCI0, DeviceObj)
|
||||
External(\_SB.PCI0.ISA, DeviceObj)
|
||||
|
||||
Scope(\_SB.PCI0.ISA) {
|
||||
Device(PEVT) {
|
||||
Name(_HID, "QEMU0001")
|
||||
/* PEST will be patched to be Zero if no such device */
|
||||
ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
|
||||
Name(PEST, 0xFFFF)
|
||||
OperationRegion(PEOR, SystemIO, PEST, 0x01)
|
||||
Field(PEOR, ByteAcc, NoLock, Preserve) {
|
||||
PEPT, 8,
|
||||
}
|
||||
|
||||
Method(_STA, 0, NotSerialized) {
|
||||
Store(PEST, Local0)
|
||||
If (LEqual(Local0, Zero)) {
|
||||
Return (0x00)
|
||||
} Else {
|
||||
Return (0x0F)
|
||||
}
|
||||
}
|
||||
|
||||
Method(RDPT, 0, NotSerialized) {
|
||||
Store(PEPT, Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
Method(WRPT, 1, NotSerialized) {
|
||||
Store(Arg0, PEPT)
|
||||
}
|
||||
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
|
||||
})
|
||||
|
||||
CreateWordField(_CRS, IO._MIN, IOMN)
|
||||
CreateWordField(_CRS, IO._MAX, IOMX)
|
||||
|
||||
Method(_INI, 0, NotSerialized) {
|
||||
Store(PEST, IOMN)
|
||||
Store(PEST, IOMX)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,386 @@
|
|||
static unsigned char acpi_pci64_length[] = {
|
||||
0x6f
|
||||
};
|
||||
static unsigned char acpi_s4_pkg[] = {
|
||||
0x8f
|
||||
};
|
||||
static unsigned char acpi_s3_name[] = {
|
||||
0x7c
|
||||
};
|
||||
static unsigned char acpi_pci32_start[] = {
|
||||
0x2f
|
||||
};
|
||||
static unsigned char acpi_pci64_valid[] = {
|
||||
0x43
|
||||
};
|
||||
static unsigned char ssdp_misc_aml[] = {
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x62,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x76,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
0x43,
|
||||
0x0,
|
||||
0x0,
|
||||
0x42,
|
||||
0x58,
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x53,
|
||||
0x55,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x23,
|
||||
0x8,
|
||||
0x13,
|
||||
0x20,
|
||||
0x10,
|
||||
0x42,
|
||||
0x5,
|
||||
0x5c,
|
||||
0x0,
|
||||
0x8,
|
||||
0x50,
|
||||
0x30,
|
||||
0x53,
|
||||
0x5f,
|
||||
0xc,
|
||||
0x78,
|
||||
0x56,
|
||||
0x34,
|
||||
0x12,
|
||||
0x8,
|
||||
0x50,
|
||||
0x30,
|
||||
0x45,
|
||||
0x5f,
|
||||
0xc,
|
||||
0x78,
|
||||
0x56,
|
||||
0x34,
|
||||
0x12,
|
||||
0x8,
|
||||
0x50,
|
||||
0x31,
|
||||
0x56,
|
||||
0x5f,
|
||||
0xa,
|
||||
0x12,
|
||||
0x8,
|
||||
0x50,
|
||||
0x31,
|
||||
0x53,
|
||||
0x5f,
|
||||
0x11,
|
||||
0xb,
|
||||
0xa,
|
||||
0x8,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x50,
|
||||
0x31,
|
||||
0x45,
|
||||
0x5f,
|
||||
0x11,
|
||||
0xb,
|
||||
0xa,
|
||||
0x8,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x50,
|
||||
0x31,
|
||||
0x4c,
|
||||
0x5f,
|
||||
0x11,
|
||||
0xb,
|
||||
0xa,
|
||||
0x8,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x10,
|
||||
0x29,
|
||||
0x5c,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x33,
|
||||
0x5f,
|
||||
0x12,
|
||||
0x6,
|
||||
0x4,
|
||||
0x1,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x34,
|
||||
0x5f,
|
||||
0x12,
|
||||
0x8,
|
||||
0x4,
|
||||
0xa,
|
||||
0x2,
|
||||
0xa,
|
||||
0x2,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x35,
|
||||
0x5f,
|
||||
0x12,
|
||||
0x6,
|
||||
0x4,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x10,
|
||||
0x40,
|
||||
0xc,
|
||||
0x5c,
|
||||
0x2f,
|
||||
0x3,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x49,
|
||||
0x53,
|
||||
0x41,
|
||||
0x5f,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x4d,
|
||||
0xa,
|
||||
0x50,
|
||||
0x45,
|
||||
0x56,
|
||||
0x54,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x51,
|
||||
0x45,
|
||||
0x4d,
|
||||
0x55,
|
||||
0x30,
|
||||
0x30,
|
||||
0x30,
|
||||
0x31,
|
||||
0x0,
|
||||
0x8,
|
||||
0x50,
|
||||
0x45,
|
||||
0x53,
|
||||
0x54,
|
||||
0xb,
|
||||
0xff,
|
||||
0xff,
|
||||
0x5b,
|
||||
0x80,
|
||||
0x50,
|
||||
0x45,
|
||||
0x4f,
|
||||
0x52,
|
||||
0x1,
|
||||
0x50,
|
||||
0x45,
|
||||
0x53,
|
||||
0x54,
|
||||
0x1,
|
||||
0x5b,
|
||||
0x81,
|
||||
0xb,
|
||||
0x50,
|
||||
0x45,
|
||||
0x4f,
|
||||
0x52,
|
||||
0x1,
|
||||
0x50,
|
||||
0x45,
|
||||
0x50,
|
||||
0x54,
|
||||
0x8,
|
||||
0x14,
|
||||
0x18,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0x70,
|
||||
0x50,
|
||||
0x45,
|
||||
0x53,
|
||||
0x54,
|
||||
0x60,
|
||||
0xa0,
|
||||
0x6,
|
||||
0x93,
|
||||
0x60,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x0,
|
||||
0xa1,
|
||||
0x4,
|
||||
0xa4,
|
||||
0xa,
|
||||
0xf,
|
||||
0x14,
|
||||
0xe,
|
||||
0x52,
|
||||
0x44,
|
||||
0x50,
|
||||
0x54,
|
||||
0x0,
|
||||
0x70,
|
||||
0x50,
|
||||
0x45,
|
||||
0x50,
|
||||
0x54,
|
||||
0x60,
|
||||
0xa4,
|
||||
0x60,
|
||||
0x14,
|
||||
0xc,
|
||||
0x57,
|
||||
0x52,
|
||||
0x50,
|
||||
0x54,
|
||||
0x1,
|
||||
0x70,
|
||||
0x68,
|
||||
0x50,
|
||||
0x45,
|
||||
0x50,
|
||||
0x54,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0x11,
|
||||
0xd,
|
||||
0xa,
|
||||
0xa,
|
||||
0x47,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x1,
|
||||
0x79,
|
||||
0x0,
|
||||
0x8b,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0xa,
|
||||
0x2,
|
||||
0x49,
|
||||
0x4f,
|
||||
0x4d,
|
||||
0x4e,
|
||||
0x8b,
|
||||
0x5f,
|
||||
0x43,
|
||||
0x52,
|
||||
0x53,
|
||||
0xa,
|
||||
0x4,
|
||||
0x49,
|
||||
0x4f,
|
||||
0x4d,
|
||||
0x58,
|
||||
0x14,
|
||||
0x18,
|
||||
0x5f,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x49,
|
||||
0x0,
|
||||
0x70,
|
||||
0x50,
|
||||
0x45,
|
||||
0x53,
|
||||
0x54,
|
||||
0x49,
|
||||
0x4f,
|
||||
0x4d,
|
||||
0x4e,
|
||||
0x70,
|
||||
0x50,
|
||||
0x45,
|
||||
0x53,
|
||||
0x54,
|
||||
0x49,
|
||||
0x4f,
|
||||
0x4d,
|
||||
0x58
|
||||
};
|
||||
static unsigned char ssdt_isa_pest[] = {
|
||||
0xd0
|
||||
};
|
||||
static unsigned char acpi_s4_name[] = {
|
||||
0x88
|
||||
};
|
||||
static unsigned char acpi_pci64_start[] = {
|
||||
0x4d
|
||||
};
|
||||
static unsigned char acpi_pci64_end[] = {
|
||||
0x5e
|
||||
};
|
||||
static unsigned char acpi_pci32_end[] = {
|
||||
0x39
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
|
||||
|
||||
DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
|
||||
{
|
||||
|
||||
/****************************************************************
|
||||
* PCI hotplug
|
||||
****************************************************************/
|
||||
|
||||
/* Objects supplied by DSDT */
|
||||
External(\_SB.PCI0, DeviceObj)
|
||||
External(\_SB.PCI0.PCEJ, MethodObj)
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
|
||||
/* Bulk generated PCI hotplug devices */
|
||||
ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
|
||||
ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
|
||||
ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
|
||||
|
||||
// Method _EJ0 can be patched by BIOS to EJ0_
|
||||
// at runtime, if the slot is detected to not support hotplug.
|
||||
// Extract the offset of the address dword and the
|
||||
// _EJ0 name to allow this patching.
|
||||
Device(SAA) {
|
||||
ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
|
||||
Name(_SUN, 0xAA)
|
||||
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
|
||||
Name(_ADR, 0xAA0000)
|
||||
ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
|
||||
Method(_EJ0, 1) {
|
||||
Return (PCEJ(_SUN))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
static unsigned char ssdt_pcihp_name[] = {
|
||||
0x33
|
||||
};
|
||||
static unsigned char ssdt_pcihp_adr[] = {
|
||||
0x44
|
||||
};
|
||||
static unsigned char ssdt_pcihp_end[] = {
|
||||
0x58
|
||||
};
|
||||
static unsigned char ssdp_pcihp_aml[] = {
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x58,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x76,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
0x43,
|
||||
0x0,
|
||||
0x0,
|
||||
0x42,
|
||||
0x58,
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x50,
|
||||
0x43,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x23,
|
||||
0x8,
|
||||
0x13,
|
||||
0x20,
|
||||
0x10,
|
||||
0x33,
|
||||
0x5c,
|
||||
0x2e,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x42,
|
||||
0x5f,
|
||||
0x50,
|
||||
0x43,
|
||||
0x49,
|
||||
0x30,
|
||||
0x5b,
|
||||
0x82,
|
||||
0x26,
|
||||
0x53,
|
||||
0x41,
|
||||
0x41,
|
||||
0x5f,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x55,
|
||||
0x4e,
|
||||
0xa,
|
||||
0xaa,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x41,
|
||||
0x44,
|
||||
0x52,
|
||||
0xc,
|
||||
0x0,
|
||||
0x0,
|
||||
0xaa,
|
||||
0x0,
|
||||
0x14,
|
||||
0xf,
|
||||
0x5f,
|
||||
0x45,
|
||||
0x4a,
|
||||
0x30,
|
||||
0x1,
|
||||
0xa4,
|
||||
0x50,
|
||||
0x43,
|
||||
0x45,
|
||||
0x4a,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x55,
|
||||
0x4e
|
||||
};
|
||||
static unsigned char ssdt_pcihp_start[] = {
|
||||
0x30
|
||||
};
|
||||
static unsigned char ssdt_pcihp_id[] = {
|
||||
0x3d
|
||||
};
|
||||
static unsigned char ssdt_pcihp_ej0[] = {
|
||||
0x4a
|
||||
};
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file is the basis for the ssdt table generated in src/acpi.c.
|
||||
* It defines the contents of the per-cpu Processor() object. At
|
||||
* runtime, a dynamically generated SSDT will contain one copy of this
|
||||
* AML snippet for every possible cpu in the system. The objects will
|
||||
* be placed in the \_SB_ namespace.
|
||||
*
|
||||
* In addition to the aml code generated from this file, the
|
||||
* src/acpi.c file creates a NTFY method with an entry for each cpu:
|
||||
* Method(NTFY, 2) {
|
||||
* If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
|
||||
* If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
|
||||
* ...
|
||||
* }
|
||||
* and a CPON array with the list of active and inactive cpus:
|
||||
* Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
|
||||
*/
|
||||
|
||||
ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
|
||||
|
||||
DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
|
||||
{
|
||||
ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
|
||||
ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
|
||||
ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
|
||||
Processor(CPAA, 0xAA, 0x00000000, 0x0) {
|
||||
ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
|
||||
Name(ID, 0xAA)
|
||||
/*
|
||||
* The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
|
||||
* CPAA and 0xAA with the appropriate CPU id (see
|
||||
* SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without
|
||||
* also updating the C code.
|
||||
*/
|
||||
Name(_HID, "ACPI0007")
|
||||
External(CPMA, MethodObj)
|
||||
External(CPST, MethodObj)
|
||||
External(CPEJ, MethodObj)
|
||||
Method(_MAT, 0) {
|
||||
Return (CPMA(ID))
|
||||
}
|
||||
Method(_STA, 0) {
|
||||
Return (CPST(ID))
|
||||
}
|
||||
Method(_EJ0, 1, NotSerialized) {
|
||||
CPEJ(ID, Arg0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
static unsigned char ssdt_proc_name[] = {
|
||||
0x28
|
||||
};
|
||||
static unsigned char ssdp_proc_aml[] = {
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x78,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0xb8,
|
||||
0x42,
|
||||
0x58,
|
||||
0x50,
|
||||
0x43,
|
||||
0x0,
|
||||
0x0,
|
||||
0x42,
|
||||
0x58,
|
||||
0x53,
|
||||
0x53,
|
||||
0x44,
|
||||
0x54,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x49,
|
||||
0x4e,
|
||||
0x54,
|
||||
0x4c,
|
||||
0x23,
|
||||
0x8,
|
||||
0x13,
|
||||
0x20,
|
||||
0x5b,
|
||||
0x83,
|
||||
0x42,
|
||||
0x5,
|
||||
0x43,
|
||||
0x50,
|
||||
0x41,
|
||||
0x41,
|
||||
0xaa,
|
||||
0x10,
|
||||
0xb0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x8,
|
||||
0x49,
|
||||
0x44,
|
||||
0x5f,
|
||||
0x5f,
|
||||
0xa,
|
||||
0xaa,
|
||||
0x8,
|
||||
0x5f,
|
||||
0x48,
|
||||
0x49,
|
||||
0x44,
|
||||
0xd,
|
||||
0x41,
|
||||
0x43,
|
||||
0x50,
|
||||
0x49,
|
||||
0x30,
|
||||
0x30,
|
||||
0x30,
|
||||
0x37,
|
||||
0x0,
|
||||
0x14,
|
||||
0xf,
|
||||
0x5f,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x54,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x43,
|
||||
0x50,
|
||||
0x4d,
|
||||
0x41,
|
||||
0x49,
|
||||
0x44,
|
||||
0x5f,
|
||||
0x5f,
|
||||
0x14,
|
||||
0xf,
|
||||
0x5f,
|
||||
0x53,
|
||||
0x54,
|
||||
0x41,
|
||||
0x0,
|
||||
0xa4,
|
||||
0x43,
|
||||
0x50,
|
||||
0x53,
|
||||
0x54,
|
||||
0x49,
|
||||
0x44,
|
||||
0x5f,
|
||||
0x5f,
|
||||
0x14,
|
||||
0xf,
|
||||
0x5f,
|
||||
0x45,
|
||||
0x4a,
|
||||
0x30,
|
||||
0x1,
|
||||
0x43,
|
||||
0x50,
|
||||
0x45,
|
||||
0x4a,
|
||||
0x49,
|
||||
0x44,
|
||||
0x5f,
|
||||
0x5f,
|
||||
0x68
|
||||
};
|
||||
static unsigned char ssdt_proc_id[] = {
|
||||
0x38
|
||||
};
|
||||
static unsigned char ssdt_proc_end[] = {
|
||||
0x78
|
||||
};
|
||||
static unsigned char ssdt_proc_start[] = {
|
||||
0x24
|
||||
};
|
|
@ -230,7 +230,7 @@ static void cmd646_update_irq(PCIIDEState *d)
|
|||
!(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) ||
|
||||
((pd->config[MRDMODE] & MRDMODE_INTR_CH1) &&
|
||||
!(pd->config[MRDMODE] & MRDMODE_BLK_CH1));
|
||||
qemu_set_irq(pd->irq[0], pci_level);
|
||||
pci_set_irq(pd, pci_level);
|
||||
}
|
||||
|
||||
/* the PCI irq level is the logical OR of the two channels */
|
||||
|
|
|
@ -116,7 +116,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
|
|||
dev->config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
|
||||
|
||||
msi_init(dev, 0x50, 1, true, false);
|
||||
d->ahci.irq = dev->irq[0];
|
||||
d->ahci.irq = pci_allocate_irq(dev);
|
||||
|
||||
pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
|
||||
&d->ahci.idp);
|
||||
|
@ -145,6 +145,7 @@ static void pci_ich9_uninit(PCIDevice *dev)
|
|||
|
||||
msi_uninit(dev);
|
||||
ahci_uninit(&d->ahci);
|
||||
qemu_free_irq(d->ahci.irq);
|
||||
}
|
||||
|
||||
static void ich_ahci_class_init(ObjectClass *klass, void *data)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
#include "qemu-common.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/range.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
@ -525,6 +526,43 @@ static const MemoryRegionOps ich9_rst_cnt_ops = {
|
|||
.endianness = DEVICE_LITTLE_ENDIAN
|
||||
};
|
||||
|
||||
Object *ich9_lpc_find(void)
|
||||
{
|
||||
bool ambig;
|
||||
Object *o = object_resolve_path_type("", TYPE_ICH9_LPC_DEVICE, &ambig);
|
||||
|
||||
if (ambig) {
|
||||
return NULL;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static void ich9_lpc_get_sci_int(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
|
||||
uint32_t value = ich9_lpc_sci_irq(lpc);
|
||||
|
||||
visit_type_uint32(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void ich9_lpc_add_properties(ICH9LPCState *lpc)
|
||||
{
|
||||
static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
|
||||
static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
|
||||
|
||||
object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32",
|
||||
ich9_lpc_get_sci_int,
|
||||
NULL, NULL, NULL, NULL);
|
||||
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
|
||||
&acpi_enable_cmd, NULL);
|
||||
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD,
|
||||
&acpi_disable_cmd, NULL);
|
||||
|
||||
ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL);
|
||||
}
|
||||
|
||||
static int ich9_lpc_initfn(PCIDevice *d)
|
||||
{
|
||||
ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
|
||||
|
@ -552,6 +590,8 @@ static int ich9_lpc_initfn(PCIDevice *d)
|
|||
ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
|
||||
1);
|
||||
|
||||
ich9_lpc_add_properties(lpc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ static void pm_update_sci(VT686PMState *s)
|
|||
ACPI_BITMASK_POWER_BUTTON_ENABLE |
|
||||
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
|
||||
ACPI_BITMASK_TIMER_ENABLE)) != 0);
|
||||
qemu_set_irq(s->dev.irq[0], sci_level);
|
||||
pci_set_irq(&s->dev, sci_level);
|
||||
/* schedule a timer interruption if needed */
|
||||
acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
|
||||
!(pmsts & ACPI_BITMASK_TIMER_STATUS));
|
||||
|
|
|
@ -73,7 +73,7 @@ static inline void hwsetup_free(HWSetup *hw)
|
|||
static inline void hwsetup_create_rom(HWSetup *hw,
|
||||
hwaddr base)
|
||||
{
|
||||
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base);
|
||||
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)
|
||||
|
|
|
@ -133,7 +133,7 @@ static void ivshmem_update_irq(IVShmemState *s, int val)
|
|||
isr ? 1 : 0, s->intrstatus, s->intrmask);
|
||||
}
|
||||
|
||||
qemu_set_irq(d->irq[0], (isr != 0));
|
||||
pci_set_irq(d, (isr != 0));
|
||||
}
|
||||
|
||||
static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val)
|
||||
|
|
|
@ -117,8 +117,19 @@ void pvpanic_init(ISABus *bus)
|
|||
isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
|
||||
}
|
||||
|
||||
#define PVPANIC_IOPORT_PROP "ioport"
|
||||
|
||||
uint16_t pvpanic_port(void)
|
||||
{
|
||||
Object *o = object_resolve_path_type("", TYPE_ISA_PVPANIC_DEVICE, NULL);
|
||||
if (!o) {
|
||||
return 0;
|
||||
}
|
||||
return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
|
||||
}
|
||||
|
||||
static Property pvpanic_isa_properties[] = {
|
||||
DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505),
|
||||
DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@ static void vfio_intx_interrupt(void *opaque)
|
|||
'A' + vdev->intx.pin);
|
||||
|
||||
vdev->intx.pending = true;
|
||||
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1);
|
||||
pci_irq_assert(&vdev->pdev);
|
||||
vfio_mmap_set_enabled(vdev, false);
|
||||
if (vdev->intx.mmap_timeout) {
|
||||
timer_mod(vdev->intx.mmap_timer,
|
||||
|
@ -320,7 +320,7 @@ static void vfio_eoi(VFIODevice *vdev)
|
|||
vdev->host.bus, vdev->host.slot, vdev->host.function);
|
||||
|
||||
vdev->intx.pending = false;
|
||||
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
|
||||
pci_irq_deassert(&vdev->pdev);
|
||||
vfio_unmask_intx(vdev);
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
|
|||
qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
|
||||
vfio_mask_intx(vdev);
|
||||
vdev->intx.pending = false;
|
||||
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
|
||||
pci_irq_deassert(&vdev->pdev);
|
||||
|
||||
/* Get an eventfd for resample/unmask */
|
||||
if (event_notifier_init(&vdev->intx.unmask, 0)) {
|
||||
|
@ -422,7 +422,7 @@ static void vfio_disable_intx_kvm(VFIODevice *vdev)
|
|||
*/
|
||||
vfio_mask_intx(vdev);
|
||||
vdev->intx.pending = false;
|
||||
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
|
||||
pci_irq_deassert(&vdev->pdev);
|
||||
|
||||
/* Tell KVM to stop listening for an INTx irqfd */
|
||||
if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {
|
||||
|
@ -493,6 +493,7 @@ static int vfio_enable_intx(VFIODevice *vdev)
|
|||
vfio_disable_interrupts(vdev);
|
||||
|
||||
vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
|
||||
pci_config_set_interrupt_pin(vdev->pdev.config, pin);
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
/*
|
||||
|
@ -552,7 +553,7 @@ static void vfio_disable_intx(VFIODevice *vdev)
|
|||
vfio_disable_intx_kvm(vdev);
|
||||
vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
|
||||
vdev->intx.pending = false;
|
||||
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
|
||||
pci_irq_deassert(&vdev->pdev);
|
||||
vfio_mmap_set_enabled(vdev, true);
|
||||
|
||||
fd = event_notifier_get_fd(&vdev->intx.interrupt);
|
||||
|
|
|
@ -328,7 +328,7 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
|
|||
}
|
||||
|
||||
s->mit_irq_level = (pending_ints != 0);
|
||||
qemu_set_irq(d->irq[0], s->mit_irq_level);
|
||||
pci_set_irq(d, s->mit_irq_level);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -409,7 +409,7 @@ static void disable_interrupt(EEPRO100State * s)
|
|||
{
|
||||
if (s->int_stat) {
|
||||
TRACE(INT, logout("interrupt disabled\n"));
|
||||
qemu_irq_lower(s->dev.irq[0]);
|
||||
pci_irq_deassert(&s->dev);
|
||||
s->int_stat = 0;
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +418,7 @@ static void enable_interrupt(EEPRO100State * s)
|
|||
{
|
||||
if (!s->int_stat) {
|
||||
TRACE(INT, logout("interrupt enabled\n"));
|
||||
qemu_irq_raise(s->dev.irq[0]);
|
||||
pci_irq_assert(&s->dev);
|
||||
s->int_stat = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -731,7 +731,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
|
|||
s = &d->ne2000;
|
||||
ne2000_setup_io(s, DEVICE(pci_dev), 0x100);
|
||||
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
|
||||
s->irq = d->dev.irq[0];
|
||||
s->irq = pci_allocate_irq(&d->dev);
|
||||
|
||||
qemu_macaddr_default_if_unset(&s->c.macaddr);
|
||||
ne2000_reset(s);
|
||||
|
@ -752,6 +752,7 @@ static void pci_ne2000_exit(PCIDevice *pci_dev)
|
|||
|
||||
memory_region_destroy(&s->io);
|
||||
qemu_del_nic(s->nic);
|
||||
qemu_free_irq(s->irq);
|
||||
}
|
||||
|
||||
static Property ne2000_properties[] = {
|
||||
|
|
|
@ -282,6 +282,7 @@ static void pci_pcnet_uninit(PCIDevice *dev)
|
|||
{
|
||||
PCIPCNetState *d = PCI_PCNET(dev);
|
||||
|
||||
qemu_free_irq(d->state.irq);
|
||||
memory_region_destroy(&d->state.mmio);
|
||||
memory_region_destroy(&d->io_bar);
|
||||
timer_del(d->state.poll_timer);
|
||||
|
@ -331,7 +332,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
|
|||
|
||||
pci_register_bar(pci_dev, 1, 0, &s->mmio);
|
||||
|
||||
s->irq = pci_dev->irq[0];
|
||||
s->irq = pci_allocate_irq(pci_dev);
|
||||
s->phys_mem_read = pci_physical_memory_read;
|
||||
s->phys_mem_write = pci_physical_memory_write;
|
||||
s->dma_opaque = pci_dev;
|
||||
|
|
|
@ -716,7 +716,7 @@ static void rtl8139_update_irq(RTL8139State *s)
|
|||
DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
|
||||
s->IntrMask);
|
||||
|
||||
qemu_set_irq(d->irq[0], (isr != 0));
|
||||
pci_set_irq(d, (isr != 0));
|
||||
}
|
||||
|
||||
static int rtl8139_RxWrap(RTL8139State *s)
|
||||
|
|
|
@ -336,7 +336,7 @@ static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
|
|||
}
|
||||
|
||||
VMW_IRPRN("Asserting line for interrupt %u", int_idx);
|
||||
qemu_set_irq(d->irq[int_idx], 1);
|
||||
pci_irq_assert(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,7 @@ static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
|
|||
assert(!s->msi_used || !msi_enabled(d));
|
||||
|
||||
VMW_IRPRN("Deasserting line for interrupt %u", lidx);
|
||||
qemu_set_irq(d->irq[lidx], 0);
|
||||
pci_irq_deassert(d);
|
||||
}
|
||||
|
||||
static void vmxnet3_update_interrupt_line_state(VMXNET3State *s, int lidx)
|
||||
|
@ -1299,6 +1299,12 @@ static void vmxnet3_update_features(VMXNET3State *s)
|
|||
}
|
||||
}
|
||||
|
||||
static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
|
||||
{
|
||||
return s->msix_used || s->msi_used || (intx ==
|
||||
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
|
||||
}
|
||||
|
||||
static void vmxnet3_activate_device(VMXNET3State *s)
|
||||
{
|
||||
int i;
|
||||
|
@ -1332,6 +1338,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||
|
||||
s->event_int_idx =
|
||||
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
|
||||
assert(vmxnet3_verify_intx(s, s->event_int_idx));
|
||||
VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
|
||||
|
||||
s->auto_int_masking =
|
||||
|
@ -1364,6 +1371,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||
/* Read interrupt number for this TX queue */
|
||||
s->txq_descr[i].intr_idx =
|
||||
VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
|
||||
assert(vmxnet3_verify_intx(s, s->txq_descr[i].intr_idx));
|
||||
|
||||
VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
|
||||
|
||||
|
@ -1411,6 +1419,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
|
|||
/* Read interrupt number for this RX queue */
|
||||
s->rxq_descr[i].intr_idx =
|
||||
VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
|
||||
assert(vmxnet3_verify_intx(s, s->rxq_descr[i].intr_idx));
|
||||
|
||||
VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ typedef struct FWCfgEntry {
|
|||
uint8_t *data;
|
||||
void *callback_opaque;
|
||||
FWCfgCallback callback;
|
||||
FWCfgReadCallback read_callback;
|
||||
} FWCfgEntry;
|
||||
|
||||
struct FWCfgState {
|
||||
|
@ -249,8 +250,12 @@ static uint8_t fw_cfg_read(FWCfgState *s)
|
|||
|
||||
if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
|
||||
ret = 0;
|
||||
else
|
||||
else {
|
||||
if (e->read_callback) {
|
||||
e->read_callback(e->callback_opaque, s->cur_offset);
|
||||
}
|
||||
ret = e->data[s->cur_offset++];
|
||||
}
|
||||
|
||||
trace_fw_cfg_read(s, ret);
|
||||
return ret;
|
||||
|
@ -381,7 +386,10 @@ static const VMStateDescription vmstate_fw_cfg = {
|
|||
}
|
||||
};
|
||||
|
||||
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
|
||||
static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
|
||||
FWCfgReadCallback callback,
|
||||
void *callback_opaque,
|
||||
void *data, size_t len)
|
||||
{
|
||||
int arch = !!(key & FW_CFG_ARCH_LOCAL);
|
||||
|
||||
|
@ -391,6 +399,13 @@ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
|
|||
|
||||
s->entries[arch][key].data = data;
|
||||
s->entries[arch][key].len = (uint32_t)len;
|
||||
s->entries[arch][key].read_callback = callback;
|
||||
s->entries[arch][key].callback_opaque = callback_opaque;
|
||||
}
|
||||
|
||||
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
|
||||
{
|
||||
fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
|
||||
}
|
||||
|
||||
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
|
||||
|
@ -444,8 +459,9 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
|||
s->entries[arch][key].callback = callback;
|
||||
}
|
||||
|
||||
void fw_cfg_add_file(FWCfgState *s, const char *filename,
|
||||
void *data, size_t len)
|
||||
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||
FWCfgReadCallback callback, void *callback_opaque,
|
||||
void *data, size_t len)
|
||||
{
|
||||
int i, index;
|
||||
size_t dsize;
|
||||
|
@ -459,7 +475,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
|
|||
index = be32_to_cpu(s->files->count);
|
||||
assert(index < FW_CFG_FILE_SLOTS);
|
||||
|
||||
fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
|
||||
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
|
||||
callback, callback_opaque, data, len);
|
||||
|
||||
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
|
||||
filename);
|
||||
|
@ -477,6 +494,12 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
|
|||
s->files->count = cpu_to_be32(index+1);
|
||||
}
|
||||
|
||||
void fw_cfg_add_file(FWCfgState *s, const char *filename,
|
||||
void *data, size_t len)
|
||||
{
|
||||
fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
|
||||
}
|
||||
|
||||
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
||||
{
|
||||
size_t len;
|
||||
|
|
|
@ -53,6 +53,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
|||
if (err) {
|
||||
goto bridge_error;
|
||||
}
|
||||
dev->config[PCI_INTERRUPT_PIN] = 0x1;
|
||||
memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
|
||||
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
|
||||
if (err) {
|
||||
|
@ -73,7 +74,6 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
|
|||
* Check whether that works well. */
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
|
||||
dev->config[PCI_INTERRUPT_PIN] = 0x1;
|
||||
return 0;
|
||||
msi_error:
|
||||
slotid_cap_cleanup(dev);
|
||||
|
|
|
@ -416,6 +416,14 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
|
|||
return b;
|
||||
}
|
||||
|
||||
PCIBus *find_i440fx(void)
|
||||
{
|
||||
PCIHostState *s = OBJECT_CHECK(PCIHostState,
|
||||
object_resolve_path("/machine/i440fx", NULL),
|
||||
TYPE_PCI_HOST_BRIDGE);
|
||||
return s ? s->bus : NULL;
|
||||
}
|
||||
|
||||
/* PIIX3 PCI to ISA bridge */
|
||||
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
|
||||
{
|
||||
|
|
|
@ -109,8 +109,18 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
|
|||
visit_type_uint64(v, &w64.end, name, errp);
|
||||
}
|
||||
|
||||
static void q35_host_get_mmcfg_size(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
|
||||
uint32_t value = e->size;
|
||||
|
||||
visit_type_uint32(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static Property mch_props[] = {
|
||||
DEFINE_PROP_UINT64("MCFG", Q35PCIHost, parent_obj.base_addr,
|
||||
DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,
|
||||
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
|
||||
DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
|
||||
mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
|
||||
|
@ -160,6 +170,10 @@ static void q35_host_initfn(Object *obj)
|
|||
q35_host_get_pci_hole64_end,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
|
||||
q35_host_get_mmcfg_size,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Leave enough space for the biggest MCFG BAR */
|
||||
/* TODO: this matches current bios behaviour, but
|
||||
* it's not a power of two, which means an MTRR
|
||||
|
@ -375,6 +389,16 @@ static int mch_init(PCIDevice *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t mch_mcfg_base(void)
|
||||
{
|
||||
bool ambiguous;
|
||||
Object *o = object_resolve_path_type("", TYPE_MCH_PCI_DEVICE, &ambiguous);
|
||||
if (!o) {
|
||||
return 0;
|
||||
}
|
||||
return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
|
||||
}
|
||||
|
||||
static void mch_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
|
72
hw/pci/pci.c
72
hw/pci/pci.c
|
@ -83,7 +83,7 @@ static const TypeInfo pcie_bus_info = {
|
|||
|
||||
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
|
||||
static void pci_update_mappings(PCIDevice *d);
|
||||
static void pci_set_irq(void *opaque, int irq_num, int level);
|
||||
static void pci_irq_handler(void *opaque, int irq_num, int level);
|
||||
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
|
||||
static void pci_del_option_rom(PCIDevice *pdev);
|
||||
|
||||
|
@ -161,7 +161,7 @@ void pci_device_deassert_intx(PCIDevice *dev)
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < PCI_NUM_PINS; ++i) {
|
||||
qemu_set_irq(dev->irq[i], 0);
|
||||
pci_irq_handler(dev, i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,6 +283,24 @@ const char *pci_root_bus_path(PCIDevice *dev)
|
|||
return rootbus->qbus.name;
|
||||
}
|
||||
|
||||
static uint64_t master_abort_mem_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
return -1ULL;
|
||||
}
|
||||
|
||||
static void master_abort_mem_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
}
|
||||
|
||||
static const MemoryRegionOps master_abort_mem_ops = {
|
||||
.read = master_abort_mem_read,
|
||||
.write = master_abort_mem_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
#define MASTER_ABORT_MEM_PRIORITY INT_MIN
|
||||
|
||||
static void pci_bus_init(PCIBus *bus, DeviceState *parent,
|
||||
const char *name,
|
||||
MemoryRegion *address_space_mem,
|
||||
|
@ -294,6 +312,14 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
|
|||
bus->address_space_mem = address_space_mem;
|
||||
bus->address_space_io = address_space_io;
|
||||
|
||||
|
||||
memory_region_init_io(&bus->master_abort_mem, OBJECT(bus),
|
||||
&master_abort_mem_ops, bus, "pci-master-abort",
|
||||
memory_region_size(bus->address_space_mem));
|
||||
memory_region_add_subregion_overlap(bus->address_space_mem,
|
||||
0, &bus->master_abort_mem,
|
||||
MASTER_ABORT_MEM_PRIORITY);
|
||||
|
||||
/* host bridge */
|
||||
QLIST_INIT(&bus->child);
|
||||
|
||||
|
@ -863,14 +889,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
|
|||
pci_dev->config_read = config_read;
|
||||
pci_dev->config_write = config_write;
|
||||
bus->devices[devfn] = pci_dev;
|
||||
pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
|
||||
pci_dev->version_id = 2; /* Current pci device vmstate version */
|
||||
return pci_dev;
|
||||
}
|
||||
|
||||
static void do_pci_unregister_device(PCIDevice *pci_dev)
|
||||
{
|
||||
qemu_free_irqs(pci_dev->irq);
|
||||
pci_dev->bus->devices[pci_dev->devfn] = NULL;
|
||||
pci_config_free(pci_dev);
|
||||
|
||||
|
@ -1175,7 +1199,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
|
|||
/* generic PCI irq support */
|
||||
|
||||
/* 0 <= irq_num <= 3. level must be 0 or 1 */
|
||||
static void pci_set_irq(void *opaque, int irq_num, int level)
|
||||
static void pci_irq_handler(void *opaque, int irq_num, int level)
|
||||
{
|
||||
PCIDevice *pci_dev = opaque;
|
||||
int change;
|
||||
|
@ -1191,6 +1215,24 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
|
|||
pci_change_irq_level(pci_dev, irq_num, change);
|
||||
}
|
||||
|
||||
static inline int pci_intx(PCIDevice *pci_dev)
|
||||
{
|
||||
return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
|
||||
}
|
||||
|
||||
qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
|
||||
{
|
||||
int intx = pci_intx(pci_dev);
|
||||
|
||||
return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
|
||||
}
|
||||
|
||||
void pci_set_irq(PCIDevice *pci_dev, int level)
|
||||
{
|
||||
int intx = pci_intx(pci_dev);
|
||||
pci_irq_handler(pci_dev, intx, level);
|
||||
}
|
||||
|
||||
/* Special hooks used by device assignment */
|
||||
void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
|
||||
{
|
||||
|
@ -2264,7 +2306,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
|
|||
Range *range = opaque;
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
|
||||
uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
|
||||
int r;
|
||||
int i;
|
||||
|
||||
if (!(cmd & PCI_COMMAND_MEMORY)) {
|
||||
return;
|
||||
|
@ -2283,17 +2325,21 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
|
|||
range_extend(range, &pref_range);
|
||||
}
|
||||
}
|
||||
for (r = 0; r < PCI_NUM_REGIONS; ++r) {
|
||||
PCIIORegion *region = &dev->io_regions[r];
|
||||
for (i = 0; i < PCI_NUM_REGIONS; ++i) {
|
||||
PCIIORegion *r = &dev->io_regions[i];
|
||||
Range region_range;
|
||||
|
||||
if (!region->size ||
|
||||
(region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
|
||||
!(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
|
||||
if (!r->size ||
|
||||
(r->type & PCI_BASE_ADDRESS_SPACE_IO) ||
|
||||
!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
|
||||
continue;
|
||||
}
|
||||
region_range.begin = pci_bar_address(dev, i, r->type, r->size);
|
||||
region_range.end = region_range.begin + r->size;
|
||||
|
||||
if (region_range.begin == PCI_BAR_UNMAPPED) {
|
||||
continue;
|
||||
}
|
||||
region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
|
||||
region_range.end = region_range.begin + region->size;
|
||||
|
||||
region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ static void hotplug_event_notify(PCIDevice *dev)
|
|||
} else if (msi_enabled(dev)) {
|
||||
msi_notify(dev, pcie_cap_flags_get_vector(dev));
|
||||
} else {
|
||||
qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
|
||||
pci_set_irq(dev, dev->exp.hpev_notified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ static void hotplug_event_clear(PCIDevice *dev)
|
|||
{
|
||||
hotplug_event_update_event_status(dev);
|
||||
if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
|
||||
qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
|
||||
pci_irq_deassert(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ static void pcie_aer_root_notify(PCIDevice *dev)
|
|||
} else if (msi_enabled(dev)) {
|
||||
msi_notify(dev, pcie_aer_root_get_vector(dev));
|
||||
} else {
|
||||
qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
|
||||
pci_irq_assert(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -768,7 +768,7 @@ void pcie_aer_root_write_config(PCIDevice *dev,
|
|||
uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
|
||||
/* 6.2.4.1.2 Interrupt Generation */
|
||||
if (!msix_enabled(dev) && !msi_enabled(dev)) {
|
||||
qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
|
||||
pci_set_irq(dev, !!(root_cmd & enabled_cmd));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,27 +24,6 @@
|
|||
#include "hw/pci/pcie_host.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
/*
|
||||
* PCI express mmcfig address
|
||||
* bit 20 - 28: bus number
|
||||
* bit 15 - 19: device number
|
||||
* bit 12 - 14: function number
|
||||
* bit 0 - 11: offset in configuration space of a given device
|
||||
*/
|
||||
#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
|
||||
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
|
||||
#define PCIE_MMCFG_BUS_BIT 20
|
||||
#define PCIE_MMCFG_BUS_MASK 0x1ff
|
||||
#define PCIE_MMCFG_DEVFN_BIT 12
|
||||
#define PCIE_MMCFG_DEVFN_MASK 0xff
|
||||
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
|
||||
#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
|
||||
PCIE_MMCFG_BUS_MASK)
|
||||
#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
|
||||
PCIE_MMCFG_DEVFN_MASK)
|
||||
#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
|
||||
|
||||
|
||||
/* a helper function to get a PCIDevice for a given mmconfig address */
|
||||
static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
|
||||
uint32_t mmcfg_addr)
|
||||
|
@ -104,9 +83,6 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
|
|||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
|
||||
#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
|
||||
|
||||
int pcie_host_init(PCIExpressHost *e)
|
||||
{
|
||||
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
|
||||
|
|
|
@ -172,7 +172,7 @@ static void shpc_interrupt_update(PCIDevice *d)
|
|||
if (msi_enabled(d) && shpc->msi_requested != level)
|
||||
msi_notify(d, 0);
|
||||
else
|
||||
qemu_set_irq(d->irq[0], level);
|
||||
pci_set_irq(d, level);
|
||||
shpc->msi_requested = level;
|
||||
}
|
||||
|
||||
|
|
|
@ -361,7 +361,7 @@ static int esp_pci_scsi_init(PCIDevice *dev)
|
|||
"esp-io", 0x80);
|
||||
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
|
||||
s->irq = dev->irq[0];
|
||||
s->irq = pci_allocate_irq(dev);
|
||||
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL);
|
||||
if (!d->hotplugged) {
|
||||
|
@ -378,6 +378,7 @@ static void esp_pci_scsi_uninit(PCIDevice *d)
|
|||
{
|
||||
PCIESPState *pci = PCI_ESP(d);
|
||||
|
||||
qemu_free_irq(pci->esp.irq);
|
||||
memory_region_destroy(&pci->io);
|
||||
}
|
||||
|
||||
|
|
|
@ -437,7 +437,7 @@ static void lsi_update_irq(LSIState *s)
|
|||
level, s->dstat, s->sist1, s->sist0);
|
||||
last_level = level;
|
||||
}
|
||||
qemu_set_irq(d->irq[0], level);
|
||||
pci_set_irq(d, level);
|
||||
|
||||
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
|
||||
DPRINTF("Handled IRQs & disconnected, looking for pending "
|
||||
|
|
|
@ -535,7 +535,7 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
|
|||
msix_notify(pci_dev, 0);
|
||||
} else {
|
||||
trace_megasas_irq_raise();
|
||||
qemu_irq_raise(pci_dev->irq[0]);
|
||||
pci_irq_assert(pci_dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1936,7 +1936,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
|
|||
s->intr_mask = val;
|
||||
if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) {
|
||||
trace_megasas_irq_lower();
|
||||
qemu_irq_lower(pci_dev->irq[0]);
|
||||
pci_irq_deassert(pci_dev);
|
||||
}
|
||||
if (megasas_intr_enabled(s)) {
|
||||
trace_megasas_intr_enabled();
|
||||
|
@ -1952,7 +1952,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
|
|||
stl_le_phys(s->producer_pa, s->reply_queue_head);
|
||||
if (!msix_enabled(pci_dev)) {
|
||||
trace_megasas_irq_lower();
|
||||
qemu_irq_lower(pci_dev->irq[0]);
|
||||
pci_irq_deassert(pci_dev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -330,7 +330,7 @@ pvscsi_update_irq_status(PVSCSIState *s)
|
|||
return;
|
||||
}
|
||||
|
||||
qemu_set_irq(d->irq[0], !!should_raise);
|
||||
pci_set_irq(d, !!should_raise);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -757,6 +757,11 @@ static void hpet_device_class_init(ObjectClass *klass, void *data)
|
|||
dc->props = hpet_device_properties;
|
||||
}
|
||||
|
||||
bool hpet_find(void)
|
||||
{
|
||||
return object_resolve_path_type("", TYPE_HPET, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo hpet_device_info = {
|
||||
.name = TYPE_HPET,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
|
|
|
@ -60,7 +60,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
|
|||
pci_conf[0x6e] = 0x00;
|
||||
pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */
|
||||
|
||||
s->irq = dev->irq[3];
|
||||
s->irq = pci_allocate_irq(dev);
|
||||
s->as = pci_get_address_space(dev);
|
||||
|
||||
usb_ehci_realize(s, DEVICE(dev), NULL);
|
||||
|
|
|
@ -1946,7 +1946,7 @@ static int usb_ohci_initfn_pci(PCIDevice *dev)
|
|||
pci_get_address_space(dev)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ohci->state.irq = dev->irq[0];
|
||||
ohci->state.irq = pci_allocate_irq(dev);
|
||||
|
||||
pci_register_bar(dev, 0, 0, &ohci->state.mem);
|
||||
return 0;
|
||||
|
|
|
@ -164,7 +164,6 @@ struct UHCIState {
|
|||
|
||||
/* Interrupts that should be raised at the end of the current frame. */
|
||||
uint32_t pending_int_mask;
|
||||
int irq_pin;
|
||||
|
||||
/* Active packets */
|
||||
QTAILQ_HEAD(, UHCIQueue) queues;
|
||||
|
@ -381,7 +380,7 @@ static void uhci_update_irq(UHCIState *s)
|
|||
} else {
|
||||
level = 0;
|
||||
}
|
||||
qemu_set_irq(s->dev.irq[s->irq_pin], level);
|
||||
pci_set_irq(&s->dev, level);
|
||||
}
|
||||
|
||||
static void uhci_reset(void *opaque)
|
||||
|
@ -1240,8 +1239,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
|
|||
/* TODO: reset value should be 0. */
|
||||
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
|
||||
|
||||
s->irq_pin = u->info.irq_pin;
|
||||
pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
|
||||
pci_config_set_interrupt_pin(pci_conf, u->info.irq_pin + 1);
|
||||
|
||||
if (s->masterbus) {
|
||||
USBPort *ports[NB_PORTS];
|
||||
|
|
|
@ -449,7 +449,6 @@ struct XHCIState {
|
|||
/*< public >*/
|
||||
|
||||
USBBus bus;
|
||||
qemu_irq irq;
|
||||
MemoryRegion mem;
|
||||
MemoryRegion mem_cap;
|
||||
MemoryRegion mem_oper;
|
||||
|
@ -739,7 +738,7 @@ static void xhci_intx_update(XHCIState *xhci)
|
|||
}
|
||||
|
||||
trace_usb_xhci_irq_intx(level);
|
||||
qemu_set_irq(xhci->irq, level);
|
||||
pci_set_irq(pci_dev, level);
|
||||
}
|
||||
|
||||
static void xhci_msix_update(XHCIState *xhci, int v)
|
||||
|
@ -797,7 +796,7 @@ static void xhci_intr_raise(XHCIState *xhci, int v)
|
|||
|
||||
if (v == 0) {
|
||||
trace_usb_xhci_irq_intx(1);
|
||||
qemu_set_irq(xhci->irq, 1);
|
||||
pci_irq_assert(pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3433,8 +3432,6 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
|
|||
|
||||
xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
|
||||
|
||||
xhci->irq = dev->irq[0];
|
||||
|
||||
memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
|
||||
memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
|
||||
"capabilities", LEN_CAP);
|
||||
|
|
|
@ -116,7 +116,7 @@ static void virtio_pci_notify(DeviceState *d, uint16_t vector)
|
|||
if (msix_enabled(&proxy->pci_dev))
|
||||
msix_notify(&proxy->pci_dev, vector);
|
||||
else
|
||||
qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
|
||||
pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
|
||||
}
|
||||
|
||||
static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
|
||||
|
@ -362,7 +362,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
|
|||
/* reading from the ISR also clears it. */
|
||||
ret = vdev->isr;
|
||||
vdev->isr = 0;
|
||||
qemu_set_irq(proxy->pci_dev.irq[0], 0);
|
||||
pci_irq_deassert(&proxy->pci_dev);
|
||||
break;
|
||||
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||
ret = vdev->config_vector;
|
||||
|
|
|
@ -153,7 +153,7 @@ struct MemoryRegion {
|
|||
bool flush_coalesced_mmio;
|
||||
MemoryRegion *alias;
|
||||
hwaddr alias_offset;
|
||||
unsigned priority;
|
||||
int priority;
|
||||
bool may_overlap;
|
||||
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
|
||||
QTAILQ_ENTRY(MemoryRegion) subregions_link;
|
||||
|
@ -779,7 +779,7 @@ void memory_region_add_subregion(MemoryRegion *mr,
|
|||
void memory_region_add_subregion_overlap(MemoryRegion *mr,
|
||||
hwaddr offset,
|
||||
MemoryRegion *subregion,
|
||||
unsigned priority);
|
||||
int priority);
|
||||
|
||||
/**
|
||||
* memory_region_get_ram_addr: Get the ram address associated with a memory
|
||||
|
|
|
@ -165,6 +165,10 @@ extern int acpi_enabled;
|
|||
extern char unsigned *acpi_tables;
|
||||
extern size_t acpi_tables_len;
|
||||
|
||||
uint8_t *acpi_table_first(void);
|
||||
uint8_t *acpi_table_next(uint8_t *current);
|
||||
unsigned acpi_table_len(void *current);
|
||||
void acpi_table_add(const QemuOpts *opts, Error **errp);
|
||||
void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
|
||||
|
||||
#endif /* !QEMU_HW_ACPI_H */
|
||||
|
|
|
@ -49,4 +49,6 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
|
|||
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
|
||||
extern const VMStateDescription vmstate_ich9_pm;
|
||||
|
||||
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
|
||||
|
||||
#endif /* HW_ACPI_ICH9_H */
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef HW_ACPI_PIIX4_H
|
||||
#define HW_ACPI_PIIX4_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
Object *piix4_pm_find(void);
|
||||
|
||||
#endif
|
|
@ -66,6 +66,8 @@ typedef struct ICH9LPCState {
|
|||
qemu_irq *ioapic;
|
||||
} ICH9LPCState;
|
||||
|
||||
Object *ich9_lpc_find(void);
|
||||
|
||||
#define Q35_MASK(bit, ms_bit, ls_bit) \
|
||||
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "hw/i386/ioapic.h"
|
||||
|
||||
#include "qemu/range.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
/* PC-style peripherals (also used by other machines). */
|
||||
|
||||
|
@ -17,10 +20,27 @@ typedef struct PcPciInfo {
|
|||
Range w64;
|
||||
} PcPciInfo;
|
||||
|
||||
#define ACPI_PM_PROP_S3_DISABLED "disable_s3"
|
||||
#define ACPI_PM_PROP_S4_DISABLED "disable_s4"
|
||||
#define ACPI_PM_PROP_S4_VAL "s4_val"
|
||||
#define ACPI_PM_PROP_SCI_INT "sci_int"
|
||||
#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd"
|
||||
#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd"
|
||||
#define ACPI_PM_PROP_PM_IO_BASE "pm_io_base"
|
||||
#define ACPI_PM_PROP_GPE0_BLK "gpe0_blk"
|
||||
#define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len"
|
||||
|
||||
struct PcGuestInfo {
|
||||
bool has_pci_info;
|
||||
bool isapc_ram_fw;
|
||||
hwaddr ram_size;
|
||||
unsigned apic_id_limit;
|
||||
bool apic_xrupt_override;
|
||||
uint64_t numa_nodes;
|
||||
uint64_t *node_mem;
|
||||
uint64_t *node_cpu;
|
||||
FWCfgState *fw_cfg;
|
||||
bool has_acpi_build;
|
||||
};
|
||||
|
||||
/* parallel.c */
|
||||
|
@ -173,6 +193,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
|
|||
MemoryRegion *pci_memory,
|
||||
MemoryRegion *ram_memory);
|
||||
|
||||
PCIBus *find_i440fx(void);
|
||||
/* piix4.c */
|
||||
extern PCIDevice *piix4_dev;
|
||||
int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
|
||||
|
@ -215,6 +236,7 @@ void pc_system_firmware_init(MemoryRegion *rom_memory,
|
|||
|
||||
/* pvpanic.c */
|
||||
void pvpanic_init(ISABus *bus);
|
||||
uint16_t pvpanic_port(void);
|
||||
|
||||
/* e820 types */
|
||||
#define E820_RAM 1
|
||||
|
|
|
@ -30,6 +30,12 @@ static inline void qemu_irq_pulse(qemu_irq irq)
|
|||
*/
|
||||
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
|
||||
|
||||
/*
|
||||
* Allocates a single IRQ. The irq is assigned with a handler, an opaque
|
||||
* data and the interrupt number.
|
||||
*/
|
||||
qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
|
||||
|
||||
/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
|
||||
* preserved. New IRQs are assigned the argument handler and opaque data.
|
||||
*/
|
||||
|
@ -37,6 +43,7 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
|
|||
void *opaque, int n);
|
||||
|
||||
void qemu_free_irqs(qemu_irq *s);
|
||||
void qemu_free_irq(qemu_irq irq);
|
||||
|
||||
/* Returns a new IRQ with opposite polarity. */
|
||||
qemu_irq qemu_irq_invert(qemu_irq irq);
|
||||
|
|
|
@ -40,11 +40,13 @@ extern bool rom_file_in_ram;
|
|||
|
||||
int rom_add_file(const char *file, const char *fw_dir,
|
||||
hwaddr addr, int32_t bootindex);
|
||||
int rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr);
|
||||
void *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||
hwaddr addr, const char *fw_file_name,
|
||||
FWCfgReadCallback fw_callback, void *callback_opaque);
|
||||
int rom_add_elf_program(const char *name, void *data, size_t datasize,
|
||||
size_t romsize, hwaddr addr);
|
||||
int rom_load_all(void);
|
||||
void rom_load_done(void);
|
||||
void rom_set_fw(FWCfgState *f);
|
||||
int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
|
||||
void *rom_ptr(hwaddr addr);
|
||||
|
@ -53,7 +55,7 @@ void do_info_roms(Monitor *mon, const QDict *qdict);
|
|||
#define rom_add_file_fixed(_f, _a, _i) \
|
||||
rom_add_file(_f, NULL, _a, _i)
|
||||
#define rom_add_blob_fixed(_f, _b, _l, _a) \
|
||||
rom_add_blob(_f, _b, _l, _a)
|
||||
(rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) ? 0 : -1)
|
||||
|
||||
#define PC_ROM_MIN_VGA 0xc0000
|
||||
#define PC_ROM_MIN_OPTION 0xc8000
|
||||
|
|
|
@ -46,12 +46,14 @@
|
|||
|
||||
#define FW_CFG_INVALID 0xffff
|
||||
|
||||
#define FW_CFG_MAX_FILE_PATH 56
|
||||
|
||||
#ifndef NO_QEMU_PROTOS
|
||||
typedef struct FWCfgFile {
|
||||
uint32_t size; /* file size */
|
||||
uint16_t select; /* write this to 0x510 to read it */
|
||||
uint16_t reserved;
|
||||
char name[56];
|
||||
char name[FW_CFG_MAX_FILE_PATH];
|
||||
} FWCfgFile;
|
||||
|
||||
typedef struct FWCfgFiles {
|
||||
|
@ -60,6 +62,7 @@ typedef struct FWCfgFiles {
|
|||
} FWCfgFiles;
|
||||
|
||||
typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
|
||||
typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset);
|
||||
|
||||
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
|
||||
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
|
||||
|
@ -70,6 +73,9 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
|||
void *callback_opaque, void *data, size_t len);
|
||||
void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
|
||||
size_t len);
|
||||
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||
FWCfgReadCallback callback, void *callback_opaque,
|
||||
void *data, size_t len);
|
||||
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
hwaddr crl_addr, hwaddr data_addr);
|
||||
|
||||
|
|
|
@ -156,4 +156,6 @@ typedef struct Q35PCIHost {
|
|||
#define MCH_PCIE_DEV 1
|
||||
#define MCH_PCIE_FUNC 0
|
||||
|
||||
uint64_t mch_mcfg_base(void);
|
||||
|
||||
#endif /* HW_Q35_H */
|
||||
|
|
|
@ -247,9 +247,6 @@ struct PCIDevice {
|
|||
PCIConfigReadFunc *config_read;
|
||||
PCIConfigWriteFunc *config_write;
|
||||
|
||||
/* IRQ objects for the INTA-INTD pins. */
|
||||
qemu_irq *irq;
|
||||
|
||||
/* Legacy PCI VGA regions */
|
||||
MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
|
||||
bool has_vga;
|
||||
|
@ -632,6 +629,29 @@ PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
|
|||
PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
|
||||
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
|
||||
|
||||
qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
|
||||
void pci_set_irq(PCIDevice *pci_dev, int level);
|
||||
|
||||
static inline void pci_irq_assert(PCIDevice *pci_dev)
|
||||
{
|
||||
pci_set_irq(pci_dev, 1);
|
||||
}
|
||||
|
||||
static inline void pci_irq_deassert(PCIDevice *pci_dev)
|
||||
{
|
||||
pci_set_irq(pci_dev, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: PCI does not work this way.
|
||||
* All the callers to this method should be fixed.
|
||||
*/
|
||||
static inline void pci_irq_pulse(PCIDevice *pci_dev)
|
||||
{
|
||||
pci_irq_assert(pci_dev);
|
||||
pci_irq_deassert(pci_dev);
|
||||
}
|
||||
|
||||
static inline int pci_is_express(const PCIDevice *d)
|
||||
{
|
||||
return d->cap_present & QEMU_PCI_CAP_EXPRESS;
|
||||
|
|
|
@ -23,6 +23,7 @@ struct PCIBus {
|
|||
PCIDevice *parent_dev;
|
||||
MemoryRegion *address_space_mem;
|
||||
MemoryRegion *address_space_io;
|
||||
MemoryRegion master_abort_mem;
|
||||
|
||||
QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
|
||||
QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
|
||||
|
|
|
@ -64,15 +64,6 @@ struct PCIExpressDevice {
|
|||
uint8_t exp_cap;
|
||||
|
||||
/* SLOT */
|
||||
unsigned int hpev_intx; /* INTx for hot plug event (0-3:INT[A-D]#)
|
||||
* default is 0 = INTA#
|
||||
* If the chip wants to use other interrupt
|
||||
* line, initialize this member with the
|
||||
* desired number.
|
||||
* If the chip dynamically changes this member,
|
||||
* also initialize it when loaded as
|
||||
* appropreately.
|
||||
*/
|
||||
bool hpev_notified; /* Logical AND of conditions for hot plug event.
|
||||
Following 6.7.3.4:
|
||||
Software Notification of Hot-Plug Events, an interrupt
|
||||
|
@ -82,15 +73,6 @@ struct PCIExpressDevice {
|
|||
/* AER */
|
||||
uint16_t aer_cap;
|
||||
PCIEAERLog aer_log;
|
||||
unsigned int aer_intx; /* INTx for error reporting
|
||||
* default is 0 = INTA#
|
||||
* If the chip wants to use other interrupt
|
||||
* line, initialize this member with the
|
||||
* desired number.
|
||||
* If the chip dynamically changes this member,
|
||||
* also initialize it when loaded as
|
||||
* appropreately.
|
||||
*/
|
||||
};
|
||||
|
||||
/* PCI express capability helper functions */
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
#define PCIE_HOST_BRIDGE(obj) \
|
||||
OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
|
||||
|
||||
#define PCIE_HOST_MCFG_BASE "MCFG"
|
||||
#define PCIE_HOST_MCFG_SIZE "mcfg_size"
|
||||
|
||||
/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
|
||||
#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
|
||||
|
||||
struct PCIExpressHost {
|
||||
PCIHostState pci;
|
||||
|
||||
|
@ -51,4 +57,25 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
|
|||
hwaddr addr,
|
||||
uint32_t size);
|
||||
|
||||
/*
|
||||
* PCI express ECAM (Enhanced Configuration Address Mapping) format.
|
||||
* AKA mmcfg address
|
||||
* bit 20 - 28: bus number
|
||||
* bit 15 - 19: device number
|
||||
* bit 12 - 14: function number
|
||||
* bit 0 - 11: offset in configuration space of a given device
|
||||
*/
|
||||
#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
|
||||
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
|
||||
#define PCIE_MMCFG_BUS_BIT 20
|
||||
#define PCIE_MMCFG_BUS_MASK 0x1ff
|
||||
#define PCIE_MMCFG_DEVFN_BIT 12
|
||||
#define PCIE_MMCFG_DEVFN_MASK 0xff
|
||||
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
|
||||
#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
|
||||
PCIE_MMCFG_BUS_MASK)
|
||||
#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
|
||||
PCIE_MMCFG_DEVFN_MASK)
|
||||
#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
|
||||
|
||||
#endif /* PCIE_HOST_H */
|
||||
|
|
|
@ -68,7 +68,7 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
|
|||
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
|
||||
void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
|
||||
void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
|
||||
unsigned priority);
|
||||
int priority);
|
||||
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
|
||||
MemoryRegion *mem);
|
||||
void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
|
||||
|
|
|
@ -71,4 +71,6 @@ struct hpet_fw_config
|
|||
} QEMU_PACKED;
|
||||
|
||||
extern struct hpet_fw_config hpet_cfg;
|
||||
|
||||
bool hpet_find(void);
|
||||
#endif
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "qemu/queue.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
struct Visitor;
|
||||
struct Error;
|
||||
|
||||
struct TypeImpl;
|
||||
typedef struct TypeImpl *Type;
|
||||
|
@ -301,7 +301,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
|
|||
struct Visitor *v,
|
||||
void *opaque,
|
||||
const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* ObjectPropertyRelease:
|
||||
|
@ -790,9 +790,30 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
|||
ObjectPropertyAccessor *get,
|
||||
ObjectPropertyAccessor *set,
|
||||
ObjectPropertyRelease *release,
|
||||
void *opaque, struct Error **errp);
|
||||
void *opaque, Error **errp);
|
||||
|
||||
void object_property_del(Object *obj, const char *name, struct Error **errp);
|
||||
void object_property_del(Object *obj, const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_uint8_ptr:
|
||||
* object_property_add_uint16_ptr:
|
||||
* object_property_add_uint32_ptr:
|
||||
* object_property_add_uint64_ptr:
|
||||
* @obj: the object to add a property to
|
||||
* @name: the name of the property
|
||||
* @v: pointer to value
|
||||
*
|
||||
* Add an integer property in memory. This function will add a
|
||||
* property of the appropriate type.
|
||||
*/
|
||||
void object_property_add_uint8_ptr(Object *obj, const char *name,
|
||||
const uint8_t *v, Error **errp);
|
||||
void object_property_add_uint16_ptr(Object *obj, const char *name,
|
||||
const uint16_t *v, Error **errp);
|
||||
void object_property_add_uint32_ptr(Object *obj, const char *name,
|
||||
const uint32_t *v, Error **errp);
|
||||
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||
const uint64_t *v, Error **Errp);
|
||||
|
||||
/**
|
||||
* object_property_find:
|
||||
|
@ -803,7 +824,7 @@ void object_property_del(Object *obj, const char *name, struct Error **errp);
|
|||
* Look up a property for an object and return its #ObjectProperty if found.
|
||||
*/
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
void object_unparent(Object *obj);
|
||||
|
||||
|
@ -818,7 +839,7 @@ void object_unparent(Object *obj);
|
|||
* Reads a property from a object.
|
||||
*/
|
||||
void object_property_get(Object *obj, struct Visitor *v, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set_str:
|
||||
|
@ -829,7 +850,7 @@ void object_property_get(Object *obj, struct Visitor *v, const char *name,
|
|||
* Writes a string value to a property.
|
||||
*/
|
||||
void object_property_set_str(Object *obj, const char *value,
|
||||
const char *name, struct Error **errp);
|
||||
const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_get_str:
|
||||
|
@ -842,7 +863,7 @@ void object_property_set_str(Object *obj, const char *value,
|
|||
* The caller should free the string.
|
||||
*/
|
||||
char *object_property_get_str(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set_link:
|
||||
|
@ -853,7 +874,7 @@ char *object_property_get_str(Object *obj, const char *name,
|
|||
* Writes an object's canonical path to a property.
|
||||
*/
|
||||
void object_property_set_link(Object *obj, Object *value,
|
||||
const char *name, struct Error **errp);
|
||||
const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_get_link:
|
||||
|
@ -866,7 +887,7 @@ void object_property_set_link(Object *obj, Object *value,
|
|||
* string or not a valid object path).
|
||||
*/
|
||||
Object *object_property_get_link(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set_bool:
|
||||
|
@ -877,7 +898,7 @@ Object *object_property_get_link(Object *obj, const char *name,
|
|||
* Writes a bool value to a property.
|
||||
*/
|
||||
void object_property_set_bool(Object *obj, bool value,
|
||||
const char *name, struct Error **errp);
|
||||
const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_get_bool:
|
||||
|
@ -889,7 +910,7 @@ void object_property_set_bool(Object *obj, bool value,
|
|||
* an error occurs (including when the property value is not a bool).
|
||||
*/
|
||||
bool object_property_get_bool(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set_int:
|
||||
|
@ -900,7 +921,7 @@ bool object_property_get_bool(Object *obj, const char *name,
|
|||
* Writes an integer value to a property.
|
||||
*/
|
||||
void object_property_set_int(Object *obj, int64_t value,
|
||||
const char *name, struct Error **errp);
|
||||
const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_get_int:
|
||||
|
@ -912,7 +933,7 @@ void object_property_set_int(Object *obj, int64_t value,
|
|||
* an error occurs (including when the property value is not an integer).
|
||||
*/
|
||||
int64_t object_property_get_int(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set:
|
||||
|
@ -926,7 +947,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
|
|||
* Writes a property to a object.
|
||||
*/
|
||||
void object_property_set(Object *obj, struct Visitor *v, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_parse:
|
||||
|
@ -938,7 +959,7 @@ void object_property_set(Object *obj, struct Visitor *v, const char *name,
|
|||
* Parses a string and writes the result into a property of an object.
|
||||
*/
|
||||
void object_property_parse(Object *obj, const char *string,
|
||||
const char *name, struct Error **errp);
|
||||
const char *name, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_print:
|
||||
|
@ -950,7 +971,7 @@ void object_property_parse(Object *obj, const char *string,
|
|||
* caller shall free the string.
|
||||
*/
|
||||
char *object_property_print(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_get_type:
|
||||
|
@ -961,7 +982,7 @@ char *object_property_print(Object *obj, const char *name,
|
|||
* Returns: The type name of the property.
|
||||
*/
|
||||
const char *object_property_get_type(Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_get_root:
|
||||
|
@ -1054,7 +1075,7 @@ Object *object_resolve_path_component(Object *parent, const gchar *part);
|
|||
* The child object itself can be retrieved using object_property_get_link().
|
||||
*/
|
||||
void object_property_add_child(Object *obj, const char *name,
|
||||
Object *child, struct Error **errp);
|
||||
Object *child, Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_link:
|
||||
|
@ -1077,7 +1098,7 @@ void object_property_add_child(Object *obj, const char *name,
|
|||
*/
|
||||
void object_property_add_link(Object *obj, const char *name,
|
||||
const char *type, Object **child,
|
||||
struct Error **errp);
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_str:
|
||||
|
@ -1092,9 +1113,9 @@ void object_property_add_link(Object *obj, const char *name,
|
|||
* property of type 'string'.
|
||||
*/
|
||||
void object_property_add_str(Object *obj, const char *name,
|
||||
char *(*get)(Object *, struct Error **),
|
||||
void (*set)(Object *, const char *, struct Error **),
|
||||
struct Error **errp);
|
||||
char *(*get)(Object *, Error **),
|
||||
void (*set)(Object *, const char *, Error **),
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_add_bool:
|
||||
|
@ -1108,9 +1129,9 @@ void object_property_add_str(Object *obj, const char *name,
|
|||
* property of type 'bool'.
|
||||
*/
|
||||
void object_property_add_bool(Object *obj, const char *name,
|
||||
bool (*get)(Object *, struct Error **),
|
||||
void (*set)(Object *, bool, struct Error **),
|
||||
struct Error **errp);
|
||||
bool (*get)(Object *, Error **),
|
||||
void (*set)(Object *, bool, Error **),
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_child_foreach:
|
||||
|
|
4
memory.c
4
memory.c
|
@ -1473,7 +1473,7 @@ void memory_region_add_subregion(MemoryRegion *mr,
|
|||
void memory_region_add_subregion_overlap(MemoryRegion *mr,
|
||||
hwaddr offset,
|
||||
MemoryRegion *subregion,
|
||||
unsigned priority)
|
||||
int priority)
|
||||
{
|
||||
subregion->may_overlap = true;
|
||||
subregion->priority = priority;
|
||||
|
@ -1506,7 +1506,7 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
|
|||
void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
|
||||
{
|
||||
MemoryRegion *parent = mr->parent;
|
||||
unsigned priority = mr->priority;
|
||||
int priority = mr->priority;
|
||||
bool may_overlap = mr->may_overlap;
|
||||
|
||||
if (addr == mr->addr || !parent) {
|
||||
|
|
60
qom/object.c
60
qom/object.c
|
@ -1344,6 +1344,66 @@ static char *qdev_get_type(Object *obj, Error **errp)
|
|||
return g_strdup(object_get_typename(obj));
|
||||
}
|
||||
|
||||
static void property_get_uint8_ptr(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t value = *(uint8_t *)opaque;
|
||||
visit_type_uint8(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void property_get_uint16_ptr(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
uint16_t value = *(uint16_t *)opaque;
|
||||
visit_type_uint16(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void property_get_uint32_ptr(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
uint32_t value = *(uint32_t *)opaque;
|
||||
visit_type_uint32(v, &value, name, errp);
|
||||
}
|
||||
|
||||
static void property_get_uint64_ptr(Object *obj, Visitor *v,
|
||||
void *opaque, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t value = *(uint64_t *)opaque;
|
||||
visit_type_uint64(v, &value, name, errp);
|
||||
}
|
||||
|
||||
void object_property_add_uint8_ptr(Object *obj, const char *name,
|
||||
const uint8_t *v, Error **errp)
|
||||
{
|
||||
object_property_add(obj, name, "uint8", property_get_uint8_ptr,
|
||||
NULL, NULL, (void *)v, errp);
|
||||
}
|
||||
|
||||
void object_property_add_uint16_ptr(Object *obj, const char *name,
|
||||
const uint16_t *v, Error **errp)
|
||||
{
|
||||
object_property_add(obj, name, "uint16", property_get_uint16_ptr,
|
||||
NULL, NULL, (void *)v, errp);
|
||||
}
|
||||
|
||||
void object_property_add_uint32_ptr(Object *obj, const char *name,
|
||||
const uint32_t *v, Error **errp)
|
||||
{
|
||||
object_property_add(obj, name, "uint32", property_get_uint32_ptr,
|
||||
NULL, NULL, (void *)v, errp);
|
||||
}
|
||||
|
||||
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||
const uint64_t *v, Error **errp)
|
||||
{
|
||||
object_property_add(obj, name, "uint64", property_get_uint64_ptr,
|
||||
NULL, NULL, (void *)v, errp);
|
||||
}
|
||||
|
||||
static void object_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Process mixed ASL/AML listing (.lst file) produced by iasl -l
|
||||
# Locate and execute ACPI_EXTRACT directives, output offset info
|
||||
#
|
||||
# Documentation of ACPI_EXTRACT_* directive tags:
|
||||
#
|
||||
# These directive tags output offset information from AML for BIOS runtime
|
||||
# table generation.
|
||||
# Each directive is of the form:
|
||||
# ACPI_EXTRACT_<TYPE> <array_name> <Operator> (...)
|
||||
# and causes the extractor to create an array
|
||||
# named <array_name> with offset, in the generated AML,
|
||||
# of an object of a given type in the following <Operator>.
|
||||
#
|
||||
# A directive must fit on a single code line.
|
||||
#
|
||||
# Object type in AML is verified, a mismatch causes a build failure.
|
||||
#
|
||||
# Directives and operators currently supported are:
|
||||
# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name()
|
||||
# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name()
|
||||
# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name()
|
||||
# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method()
|
||||
# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name()
|
||||
# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block
|
||||
# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor()
|
||||
# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1
|
||||
# ACPI_EXTRACT_PKG_START - start of Package block
|
||||
#
|
||||
# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode
|
||||
#
|
||||
# ACPI_EXTRACT is not allowed anywhere else in code, except in comments.
|
||||
|
||||
import re;
|
||||
import sys;
|
||||
import fileinput;
|
||||
|
||||
aml = []
|
||||
asl = []
|
||||
output = {}
|
||||
debug = ""
|
||||
|
||||
class asl_line:
|
||||
line = None
|
||||
lineno = None
|
||||
aml_offset = None
|
||||
|
||||
def die(diag):
|
||||
sys.stderr.write("Error: %s; %s\n" % (diag, debug))
|
||||
sys.exit(1)
|
||||
|
||||
#Store an ASL command, matching AML offset, and input line (for debugging)
|
||||
def add_asl(lineno, line):
|
||||
l = asl_line()
|
||||
l.line = line
|
||||
l.lineno = lineno
|
||||
l.aml_offset = len(aml)
|
||||
asl.append(l)
|
||||
|
||||
#Store an AML byte sequence
|
||||
#Verify that offset output by iasl matches # of bytes so far
|
||||
def add_aml(offset, line):
|
||||
o = int(offset, 16);
|
||||
# Sanity check: offset must match size of code so far
|
||||
if (o != len(aml)):
|
||||
die("Offset 0x%x != 0x%x" % (o, len(aml)))
|
||||
# Strip any trailing dots and ASCII dump after "
|
||||
line = re.sub(r'\s*\.*\s*".*$',"", line)
|
||||
# Strip traling whitespace
|
||||
line = re.sub(r'\s+$',"", line)
|
||||
# Strip leading whitespace
|
||||
line = re.sub(r'^\s+',"", line)
|
||||
# Split on whitespace
|
||||
code = re.split(r'\s+', line)
|
||||
for c in code:
|
||||
# Require a legal hex number, two digits
|
||||
if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))):
|
||||
die("Unexpected octet %s" % c);
|
||||
aml.append(int(c, 16));
|
||||
|
||||
# Process aml bytecode array, decoding AML
|
||||
def aml_pkglen_bytes(offset):
|
||||
# PkgLength can be multibyte. Bits 8-7 give the # of extra bytes.
|
||||
pkglenbytes = aml[offset] >> 6;
|
||||
return pkglenbytes + 1
|
||||
|
||||
def aml_pkglen(offset):
|
||||
pkgstart = offset
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
pkglen = aml[offset] & 0x3F
|
||||
# If multibyte, first nibble only uses bits 0-3
|
||||
if ((pkglenbytes > 1) and (pkglen & 0x30)):
|
||||
die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" %
|
||||
(pkglen, pkglen))
|
||||
offset += 1
|
||||
pkglenbytes -= 1
|
||||
for i in range(pkglenbytes):
|
||||
pkglen |= aml[offset + i] << (i * 8 + 4)
|
||||
if (len(aml) < pkgstart + pkglen):
|
||||
die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" %
|
||||
(pkglen, offset, len(aml)))
|
||||
return pkglen
|
||||
|
||||
# Given method offset, find its NameString offset
|
||||
def aml_method_string(offset):
|
||||
#0x14 MethodOp PkgLength NameString MethodFlags TermList
|
||||
if (aml[offset] != 0x14):
|
||||
die( "Method offset 0x%x: expected 0x14 actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
offset += 1;
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
offset += pkglenbytes;
|
||||
return offset;
|
||||
|
||||
# Given name offset, find its NameString offset
|
||||
def aml_name_string(offset):
|
||||
#0x08 NameOp NameString DataRef
|
||||
if (aml[offset] != 0x08):
|
||||
die( "Name offset 0x%x: expected 0x08 actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
offset += 1
|
||||
# Block Name Modifier. Skip it.
|
||||
if (aml[offset] == 0x5c or aml[offset] == 0x5e):
|
||||
offset += 1
|
||||
return offset;
|
||||
|
||||
# Given data offset, find 8 byte buffer offset
|
||||
def aml_data_buffer8(offset):
|
||||
#0x08 NameOp NameString DataRef
|
||||
expect = [0x11, 0x0B, 0x0A, 0x08]
|
||||
if (aml[offset:offset+4] != expect):
|
||||
die( "Name offset 0x%x: expected %s actual %s" %
|
||||
(offset, aml[offset:offset+4], expect))
|
||||
return offset + len(expect)
|
||||
|
||||
# Given data offset, find dword const offset
|
||||
def aml_data_dword_const(offset):
|
||||
#0x08 NameOp NameString DataRef
|
||||
if (aml[offset] != 0x0C):
|
||||
die( "Name offset 0x%x: expected 0x0C actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
return offset + 1;
|
||||
|
||||
# Given data offset, find word const offset
|
||||
def aml_data_word_const(offset):
|
||||
#0x08 NameOp NameString DataRef
|
||||
if (aml[offset] != 0x0B):
|
||||
die( "Name offset 0x%x: expected 0x0B actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
return offset + 1;
|
||||
|
||||
# Given data offset, find byte const offset
|
||||
def aml_data_byte_const(offset):
|
||||
#0x08 NameOp NameString DataRef
|
||||
if (aml[offset] != 0x0A):
|
||||
die( "Name offset 0x%x: expected 0x0A actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
return offset + 1;
|
||||
|
||||
# Find name'd buffer8
|
||||
def aml_name_buffer8(offset):
|
||||
return aml_data_buffer8(aml_name_string(offset) + 4)
|
||||
|
||||
# Given name offset, find dword const offset
|
||||
def aml_name_dword_const(offset):
|
||||
return aml_data_dword_const(aml_name_string(offset) + 4)
|
||||
|
||||
# Given name offset, find word const offset
|
||||
def aml_name_word_const(offset):
|
||||
return aml_data_word_const(aml_name_string(offset) + 4)
|
||||
|
||||
# Given name offset, find byte const offset
|
||||
def aml_name_byte_const(offset):
|
||||
return aml_data_byte_const(aml_name_string(offset) + 4)
|
||||
|
||||
def aml_device_start(offset):
|
||||
#0x5B 0x82 DeviceOp PkgLength NameString
|
||||
if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)):
|
||||
die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" %
|
||||
(offset, aml[offset], aml[offset + 1]));
|
||||
return offset
|
||||
|
||||
def aml_device_string(offset):
|
||||
#0x5B 0x82 DeviceOp PkgLength NameString
|
||||
start = aml_device_start(offset)
|
||||
offset += 2
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
offset += pkglenbytes
|
||||
return offset
|
||||
|
||||
def aml_device_end(offset):
|
||||
start = aml_device_start(offset)
|
||||
offset += 2
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
pkglen = aml_pkglen(offset)
|
||||
return offset + pkglen
|
||||
|
||||
def aml_processor_start(offset):
|
||||
#0x5B 0x83 ProcessorOp PkgLength NameString ProcID
|
||||
if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)):
|
||||
die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" %
|
||||
(offset, aml[offset], aml[offset + 1]));
|
||||
return offset
|
||||
|
||||
def aml_processor_string(offset):
|
||||
#0x5B 0x83 ProcessorOp PkgLength NameString ProcID
|
||||
start = aml_processor_start(offset)
|
||||
offset += 2
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
offset += pkglenbytes
|
||||
return offset
|
||||
|
||||
def aml_processor_end(offset):
|
||||
start = aml_processor_start(offset)
|
||||
offset += 2
|
||||
pkglenbytes = aml_pkglen_bytes(offset)
|
||||
pkglen = aml_pkglen(offset)
|
||||
return offset + pkglen
|
||||
|
||||
def aml_package_start(offset):
|
||||
offset = aml_name_string(offset) + 4
|
||||
# 0x12 PkgLength NumElements PackageElementList
|
||||
if (aml[offset] != 0x12):
|
||||
die( "Name offset 0x%x: expected 0x12 actual 0x%x" %
|
||||
(offset, aml[offset]));
|
||||
offset += 1
|
||||
return offset + aml_pkglen_bytes(offset) + 1
|
||||
|
||||
lineno = 0
|
||||
for line in fileinput.input():
|
||||
# Strip trailing newline
|
||||
line = line.rstrip();
|
||||
# line number and debug string to output in case of errors
|
||||
lineno = lineno + 1
|
||||
debug = "input line %d: %s" % (lineno, line)
|
||||
#ASL listing: space, then line#, then ...., then code
|
||||
pasl = re.compile('^\s+([0-9]+)(:\s\s|\.\.\.\.)\s*')
|
||||
m = pasl.search(line)
|
||||
if (m):
|
||||
add_asl(lineno, pasl.sub("", line));
|
||||
# AML listing: offset in hex, then ...., then code
|
||||
paml = re.compile('^([0-9A-Fa-f]+)(:\s\s|\.\.\.\.)\s*')
|
||||
m = paml.search(line)
|
||||
if (m):
|
||||
add_aml(m.group(1), paml.sub("", line))
|
||||
|
||||
# Now go over code
|
||||
# Track AML offset of a previous non-empty ASL command
|
||||
prev_aml_offset = -1
|
||||
for i in range(len(asl)):
|
||||
debug = "input line %d: %s" % (asl[i].lineno, asl[i].line)
|
||||
|
||||
l = asl[i].line
|
||||
|
||||
# skip if not an extract directive
|
||||
a = len(re.findall(r'ACPI_EXTRACT', l))
|
||||
if (not a):
|
||||
# If not empty, store AML offset. Will be used for sanity checks
|
||||
# IASL seems to put {}. at random places in the listing.
|
||||
# Ignore any non-words for the purpose of this test.
|
||||
m = re.search(r'\w+', l)
|
||||
if (m):
|
||||
prev_aml_offset = asl[i].aml_offset
|
||||
continue
|
||||
|
||||
if (a > 1):
|
||||
die("Expected at most one ACPI_EXTRACT per line, actual %d" % a)
|
||||
|
||||
mext = re.search(r'''
|
||||
^\s* # leading whitespace
|
||||
/\*\s* # start C comment
|
||||
(ACPI_EXTRACT_\w+) # directive: group(1)
|
||||
\s+ # whitspace separates directive from array name
|
||||
(\w+) # array name: group(2)
|
||||
\s*\*/ # end of C comment
|
||||
\s*$ # trailing whitespace
|
||||
''', l, re.VERBOSE)
|
||||
if (not mext):
|
||||
die("Stray ACPI_EXTRACT in input")
|
||||
|
||||
# previous command must have produced some AML,
|
||||
# otherwise we are in a middle of a block
|
||||
if (prev_aml_offset == asl[i].aml_offset):
|
||||
die("ACPI_EXTRACT directive in the middle of a block")
|
||||
|
||||
directive = mext.group(1)
|
||||
array = mext.group(2)
|
||||
offset = asl[i].aml_offset
|
||||
|
||||
if (directive == "ACPI_EXTRACT_ALL_CODE"):
|
||||
if array in output:
|
||||
die("%s directive used more than once" % directive)
|
||||
output[array] = aml
|
||||
continue
|
||||
if (directive == "ACPI_EXTRACT_NAME_BUFFER8"):
|
||||
offset = aml_name_buffer8(offset)
|
||||
elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
|
||||
offset = aml_name_dword_const(offset)
|
||||
elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):
|
||||
offset = aml_name_word_const(offset)
|
||||
elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"):
|
||||
offset = aml_name_byte_const(offset)
|
||||
elif (directive == "ACPI_EXTRACT_NAME_STRING"):
|
||||
offset = aml_name_string(offset)
|
||||
elif (directive == "ACPI_EXTRACT_METHOD_STRING"):
|
||||
offset = aml_method_string(offset)
|
||||
elif (directive == "ACPI_EXTRACT_DEVICE_START"):
|
||||
offset = aml_device_start(offset)
|
||||
elif (directive == "ACPI_EXTRACT_DEVICE_STRING"):
|
||||
offset = aml_device_string(offset)
|
||||
elif (directive == "ACPI_EXTRACT_DEVICE_END"):
|
||||
offset = aml_device_end(offset)
|
||||
elif (directive == "ACPI_EXTRACT_PROCESSOR_START"):
|
||||
offset = aml_processor_start(offset)
|
||||
elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"):
|
||||
offset = aml_processor_string(offset)
|
||||
elif (directive == "ACPI_EXTRACT_PROCESSOR_END"):
|
||||
offset = aml_processor_end(offset)
|
||||
elif (directive == "ACPI_EXTRACT_PKG_START"):
|
||||
offset = aml_package_start(offset)
|
||||
else:
|
||||
die("Unsupported directive %s" % directive)
|
||||
|
||||
if array not in output:
|
||||
output[array] = []
|
||||
output[array].append(offset)
|
||||
|
||||
debug = "at end of file"
|
||||
|
||||
def get_value_type(maxvalue):
|
||||
#Use type large enough to fit the table
|
||||
if (maxvalue >= 0x10000):
|
||||
return "int"
|
||||
elif (maxvalue >= 0x100):
|
||||
return "short"
|
||||
else:
|
||||
return "char"
|
||||
|
||||
# Pretty print output
|
||||
for array in output.keys():
|
||||
otype = get_value_type(max(output[array]))
|
||||
odata = []
|
||||
for value in output[array]:
|
||||
odata.append("0x%x" % value)
|
||||
sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array))
|
||||
sys.stdout.write(",\n".join(odata))
|
||||
sys.stdout.write('\n};\n');
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Read a preprocessed ASL listing and put each ACPI_EXTRACT
|
||||
# directive in a comment, to make iasl skip it.
|
||||
# We also put each directive on a new line, the machinery
|
||||
# in tools/acpi_extract.py requires this.
|
||||
|
||||
import re;
|
||||
import sys;
|
||||
import fileinput;
|
||||
|
||||
def die(diag):
|
||||
sys.stderr.write("Error: %s\n" % (diag))
|
||||
sys.exit(1)
|
||||
|
||||
# Note: () around pattern make split return matched string as part of list
|
||||
psplit = re.compile(r''' (
|
||||
\b # At word boundary
|
||||
ACPI_EXTRACT_\w+ # directive
|
||||
\s+ # some whitespace
|
||||
\w+ # array name
|
||||
)''', re.VERBOSE);
|
||||
|
||||
lineno = 0
|
||||
for line in fileinput.input():
|
||||
# line number and debug string to output in case of errors
|
||||
lineno = lineno + 1
|
||||
debug = "input line %d: %s" % (lineno, line.rstrip())
|
||||
|
||||
s = psplit.split(line);
|
||||
# The way split works, each odd item is the matching ACPI_EXTRACT directive.
|
||||
# Put each in a comment, and on a line by itself.
|
||||
for i in range(len(s)):
|
||||
if (i % 2):
|
||||
sys.stdout.write("\n/* %s */\n" % s[i])
|
||||
else:
|
||||
sys.stdout.write(s[i])
|
|
@ -0,0 +1,4 @@
|
|||
cd x86_64-softmmu
|
||||
for file in hw/i386/*.hex; do
|
||||
cp -f $file ../$file.generated
|
||||
done
|
3
vl.c
3
vl.c
|
@ -4336,6 +4336,9 @@ int main(int argc, char **argv, char **envp)
|
|||
qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
|
||||
qemu_run_machine_init_done_notifiers();
|
||||
|
||||
/* Done notifiers can load ROMs */
|
||||
rom_load_done();
|
||||
|
||||
qemu_system_reset(VMRESET_SILENT);
|
||||
if (loadvm) {
|
||||
if (load_vmstate(loadvm) < 0) {
|
||||
|
|
Loading…
Reference in New Issue