piix4acpi.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 557 行 · 第 1/2 页

C
557
字号
/* * PIIX4 ACPI controller emulation * * Winston liwen Wang, winston.l.wang@intel.com * Copyright (c) 2006 , Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"#include <xen/hvm/ioreq.h>#include <xen/hvm/params.h>/* PM1a_CNT bits, as defined in the ACPI specification. */#define SCI_EN            (1 <<  0)#define GBL_RLS           (1 <<  2)#define SLP_TYP_Sx        (7 << 10)#define SLP_EN            (1 << 13)/* Sleep state type codes as defined by the \_Sx objects in the DSDT. *//* These must be kept in sync with the DSDT (hvmloader/acpi/dsdt.asl) */#define SLP_TYP_S4        (6 << 10)#define SLP_TYP_S3        (5 << 10)#define SLP_TYP_S5        (7 << 10)#define ACPI_DBG_IO_ADDR  0xb044#define ACPI_PHP_IO_ADDR  0x10c0#define PHP_EVT_ADD     0x0#define PHP_EVT_REMOVE  0x3#define ACPI_SCI_IRQ 9/* The bit in GPE0_STS/EN to notify the pci hotplug event */#define ACPI_PHP_GPE_BIT 3#define ACPI_PHP_SLOT_NUM PHP_SLOT_LENtypedef struct AcpiDeviceState AcpiDeviceState;AcpiDeviceState *acpi_device_table;typedef struct PCIAcpiState {    PCIDevice dev;    uint16_t pm1_control; /* pm1a_ECNT_BLK */} PCIAcpiState;typedef struct GPEState {    /* GPE0 block */    uint8_t gpe0_sts[ACPI_GPE0_BLK_LEN / 2];    uint8_t gpe0_en[ACPI_GPE0_BLK_LEN / 2];    /* SCI IRQ level */    uint8_t sci_asserted;} GPEState;GPEState gpe_state;typedef struct PHPSlots {    struct {        uint8_t status;    /* Apaptor stats */    } slot[ACPI_PHP_SLOT_NUM];    uint8_t plug_evt;      /* slot|event slot:0-no event;1-1st. event:0-remove;1-add */} PHPSlots;PHPSlots php_slots;int s3_shutdown_flag;static void piix4acpi_save(QEMUFile *f, void *opaque){    PCIAcpiState *s = opaque;    pci_device_save(&s->dev, f);    qemu_put_be16s(f, &s->pm1_control);}static int piix4acpi_load(QEMUFile *f, void *opaque, int version_id){    PCIAcpiState *s = opaque;    int ret;    if (version_id > 1)         return -EINVAL;    ret = pci_device_load(&s->dev, f);    if (ret < 0)        return ret;    qemu_get_be16s(f, &s->pm1_control);    return 0;}static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val){    PCIAcpiState *s = opaque;    s->pm1_control = (s->pm1_control & 0xff00) | (val & 0xff);}static uint32_t acpiPm1Control_readb(void *opaque, uint32_t addr){    PCIAcpiState *s = opaque;    /* Mask out the write-only bits */    return (uint8_t)(s->pm1_control & ~(GBL_RLS|SLP_EN));}static void acpi_shutdown(uint32_t val){    if (!(val & SLP_EN))        return;    switch (val & SLP_TYP_Sx) {    case SLP_TYP_S3:        s3_shutdown_flag = 1;        qemu_system_reset();        s3_shutdown_flag = 0;        cmos_set_s3_resume();        xc_set_hvm_param(xc_handle, domid, HVM_PARAM_ACPI_S_STATE, 3);        break;    case SLP_TYP_S4:    case SLP_TYP_S5:        qemu_system_shutdown_request();        break;    default:        break;    }}static void acpiPm1ControlP1_writeb(void *opaque, uint32_t addr, uint32_t val){    PCIAcpiState *s = opaque;    val <<= 8;    s->pm1_control = ((s->pm1_control & 0xff) | val) & ~SLP_EN;    acpi_shutdown(val);}static uint32_t acpiPm1ControlP1_readb(void *opaque, uint32_t addr){    PCIAcpiState *s = opaque;    /* Mask out the write-only bits */    return (uint8_t)((s->pm1_control & ~(GBL_RLS|SLP_EN)) >> 8);}static void acpiPm1Control_writew(void *opaque, uint32_t addr, uint32_t val){    PCIAcpiState *s = opaque;    s->pm1_control = val & ~SLP_EN;    acpi_shutdown(val);}static uint32_t acpiPm1Control_readw(void *opaque, uint32_t addr){    PCIAcpiState *s = opaque;    /* Mask out the write-only bits */    return (s->pm1_control & ~(GBL_RLS|SLP_EN));}static void acpi_map(PCIDevice *pci_dev, int region_num,                     uint32_t addr, uint32_t size, int type){    PCIAcpiState *d = (PCIAcpiState *)pci_dev;    /* Byte access */    register_ioport_write(addr + 4, 1, 1, acpiPm1Control_writeb, d);    register_ioport_read(addr + 4, 1, 1, acpiPm1Control_readb, d);    register_ioport_write(addr + 4 + 1, 1, 1, acpiPm1ControlP1_writeb, d);    register_ioport_read(addr + 4 +1, 1, 1, acpiPm1ControlP1_readb, d);    /* Word access */    register_ioport_write(addr + 4, 2, 2, acpiPm1Control_writew, d);    register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d);}#ifdef CONFIG_PASSTHROUGHstatic inline int test_bit(uint8_t *map, int bit){    return ( map[bit / 8] & (1 << (bit % 8)) );}static inline void set_bit(uint8_t *map, int bit){    map[bit / 8] |= (1 << (bit % 8));}static inline void clear_bit(uint8_t *map, int bit){    map[bit / 8] &= ~(1 << (bit % 8));}extern FILE *logfile;static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val){#if defined(DEBUG)    printf("ACPI: DBG: 0x%08x\n", val);#endif    fprintf(logfile, "ACPI:debug: write addr=0x%x, val=0x%x.\n", addr, val);}/* * simple PCI hotplug controller IO  * ACPI_PHP_IO_ADDR + : * 0 - the hotplug description: slot(|event(remove/add);  * 1 - 1st php slot ctr/sts reg * 2 - 2nd php slot ctr/sts reg * ...... */static uint32_t acpi_php_readb(void *opaque, uint32_t addr){    PHPSlots *hotplug_slots = opaque;    int num;    uint32_t val;     switch (addr)    {    case ACPI_PHP_IO_ADDR:        val = hotplug_slots->plug_evt;        break;    default:        num = addr - ACPI_PHP_IO_ADDR - 1;        val = hotplug_slots->slot[num].status;    }    fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%x.\n",            addr, val);    return val;}static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val){    PHPSlots *hotplug_slots = opaque;    int php_slot;    fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n",            addr, val);    switch (addr)    {    case ACPI_PHP_IO_ADDR:        break;    default:        php_slot = addr - ACPI_PHP_IO_ADDR - 1;        if ( val == 0x1 ) { /* Eject command */            /* make _STA of the slot 0 */            hotplug_slots->slot[php_slot].status = 0;            /* clear the hotplug event */            hotplug_slots->plug_evt = 0;            /* power off the slot */            power_off_php_slot(php_slot);            /* signal the CP ACPI hot remove done. */            xenstore_record_dm_state("pci-removed");        }    }}static void pcislots_save(QEMUFile* f, void* opaque){    PHPSlots *s = (PHPSlots*)opaque;    int i;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?