mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
+43
-7
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+4
-4
@@ -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;
|
||||
|
||||
+26
-5
@@ -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;
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user