piix4acpi.c

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

C
557
字号
    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {        qemu_put_8s( f, &s->slot[i].status);    }    qemu_put_8s(f, &s->plug_evt);}static int pcislots_load(QEMUFile* f, void* opaque, int version_id){    PHPSlots *s = (PHPSlots*)opaque;    int i;    if (version_id != 1)        return -EINVAL;    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {        qemu_get_8s( f, &s->slot[i].status);    }    qemu_get_8s(f, &s->plug_evt);    return 0;}static void php_slots_init(void){    PHPSlots *slots = &php_slots;    int i;    memset(slots, 0, sizeof(PHPSlots));    /* update the pci slot status */    for ( i = 0; i < PHP_SLOT_LEN; i++ ) {        if ( test_pci_slot( PHP_TO_PCI_SLOT(i) ) == 1 )            slots->slot[i].status = 0xf;    }    /* ACPI PCI hotplug controller */    register_ioport_read(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_readb, slots);    register_ioport_write(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_writeb, slots);    register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, slots);}/* GPEx_STS occupy 1st half of the block, while GPEx_EN 2nd half */static uint32_t gpe_sts_read(void *opaque, uint32_t addr){    GPEState *s = opaque;    return s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS];}/* write 1 to clear specific GPE bits */static void gpe_sts_write(void *opaque, uint32_t addr, uint32_t val){    GPEState *s = opaque;    int hotplugged = 0;    fprintf(logfile, "gpe_sts_write: addr=0x%x, val=0x%x.\n", addr, val);    hotplugged = test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT);    s->gpe0_sts[addr - ACPI_GPE0_BLK_ADDRESS] &= ~val;    if ( s->sci_asserted &&         hotplugged &&         !test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT)) {        fprintf(logfile, "Clear the GPE0_STS bit for ACPI hotplug & deassert the IRQ.\n");        pic_set_irq(ACPI_SCI_IRQ, 0);    }}static uint32_t gpe_en_read(void *opaque, uint32_t addr){    GPEState *s = opaque;    return s->gpe0_en[addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2)];}/* write 0 to clear en bit */static void gpe_en_write(void *opaque, uint32_t addr, uint32_t val){    GPEState *s = opaque;    int reg_count;    fprintf(logfile, "gpe_en_write: addr=0x%x, val=0x%x.\n", addr, val);    reg_count = addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2);    s->gpe0_en[reg_count] = val;    /* If disable GPE bit right after generating SCI on it,      * need deassert the intr to avoid redundant intrs     */    if ( s->sci_asserted &&         reg_count == (ACPI_PHP_GPE_BIT / 8) &&         !(val & (1 << (ACPI_PHP_GPE_BIT % 8))) ) {        fprintf(logfile, "deassert due to disable GPE bit.\n");        s->sci_asserted = 0;        pic_set_irq(ACPI_SCI_IRQ, 0);    }}static void gpe_save(QEMUFile* f, void* opaque){    GPEState *s = (GPEState*)opaque;    int i;    for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {        qemu_put_8s(f, &s->gpe0_sts[i]);        qemu_put_8s(f, &s->gpe0_en[i]);    }    qemu_put_8s(f, &s->sci_asserted);    if ( s->sci_asserted ) {        fprintf(logfile, "gpe_save with sci asserted!\n");    }}static int gpe_load(QEMUFile* f, void* opaque, int version_id){    GPEState *s = (GPEState*)opaque;    int i;    if (version_id != 1)        return -EINVAL;    for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {        qemu_get_8s(f, &s->gpe0_sts[i]);        qemu_get_8s(f, &s->gpe0_en[i]);    }    qemu_get_8s(f, &s->sci_asserted);    return 0;}static void gpe_acpi_init(void){    GPEState *s = &gpe_state;    memset(s, 0, sizeof(GPEState));    register_ioport_read(ACPI_GPE0_BLK_ADDRESS,                         ACPI_GPE0_BLK_LEN / 2,                         1,                         gpe_sts_read,                         s);    register_ioport_read(ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2,                         ACPI_GPE0_BLK_LEN / 2,                         1,                         gpe_en_read,                         s);    register_ioport_write(ACPI_GPE0_BLK_ADDRESS,                          ACPI_GPE0_BLK_LEN / 2,                          1,                          gpe_sts_write,                          s);    register_ioport_write(ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2,                          ACPI_GPE0_BLK_LEN / 2,                          1,                          gpe_en_write,                          s);    register_savevm("gpe", 0, 1, gpe_save, gpe_load, s);}static void acpi_sci_intr(GPEState *s){    if ( !test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT) &&         test_bit(&s->gpe0_en[0], ACPI_PHP_GPE_BIT) ) {        set_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT);        s->sci_asserted = 1;        pic_set_irq(ACPI_SCI_IRQ, 1);        fprintf(logfile, "generate a sci for PHP.\n");    }}void acpi_php_del(int pci_slot){    GPEState *s = &gpe_state;    PHPSlots *hotplug_slots = &php_slots;    int php_slot = PCI_TO_PHP_SLOT(pci_slot);    if ( pci_slot < PHP_SLOT_START || pci_slot >= PHP_SLOT_END ) {        fprintf(logfile, "not find the pci slot %d when hot remove.\n", pci_slot);        return;    }    /* update the php controller status */    hotplug_slots->plug_evt = (((php_slot+1) << 4) | PHP_EVT_REMOVE);    /* generate a SCI interrupt */    acpi_sci_intr(s);}void acpi_php_add(int pci_slot){    GPEState *s = &gpe_state;    PHPSlots *hotplug_slots = &php_slots;    int php_slot = PCI_TO_PHP_SLOT(pci_slot);    char ret_str[30];    if ( pci_slot < PHP_SLOT_START || pci_slot >= PHP_SLOT_END ) {        fprintf(logfile, "hot add pci slot %d exceed.\n", pci_slot);        if ( pci_slot == 0 )            sprintf(ret_str, "no free hotplug slots");        else if ( pci_slot == -1 )            sprintf(ret_str, "wrong bdf or vslot");        if ( strlen(ret_str) > 0 )            xenstore_record_dm("parameter", ret_str);        return;    }    /* update the php controller status */    hotplug_slots->plug_evt = (((php_slot+1) << 4) | PHP_EVT_ADD);    /* update the slot status as present */    hotplug_slots->slot[php_slot].status = 0xf;    /* power on the slot */    power_on_php_slot(php_slot);    /* tell Control panel which slot for the new pass-throgh dev */    sprintf(ret_str, "0x%x", pci_slot);    xenstore_record_dm("parameter", ret_str);    /* signal the CP ACPI hot insert done */    xenstore_record_dm_state("pci-inserted");    /* generate a SCI interrupt */    acpi_sci_intr(s);}#endif /* CONFIG_PASSTHROUGH *//* PIIX4 acpi pci configuration space, func 2 */void pci_piix4_acpi_init(PCIBus *bus, int devfn){    PCIAcpiState *d;    uint8_t *pci_conf;    /* register a function 2 of PIIX4 */    d = (PCIAcpiState *)pci_register_device(        bus, "PIIX4 ACPI", sizeof(PCIAcpiState),        devfn, NULL, NULL);    pci_conf = d->dev.config;    pci_conf[0x00] = 0x86;  /* Intel */    pci_conf[0x01] = 0x80;    pci_conf[0x02] = 0x13;    pci_conf[0x03] = 0x71;    pci_conf[0x08] = 0x01;  /* B0 stepping */    pci_conf[0x09] = 0x00;  /* base class */    pci_conf[0x0a] = 0x80;  /* Sub class */    pci_conf[0x0b] = 0x06;    pci_conf[0x0e] = 0x00;    pci_conf[0x3d] = 0x01;  /* Hardwired to PIRQA is used */    /* PMBA POWER MANAGEMENT BASE ADDRESS, hardcoded to 0x1f40      * to make shutdown work for IPF, due to IPF Guest Firmware      * will enumerate pci devices.      *     * TODO:  if Guest Firmware or Guest OS will change this PMBA,     * More logic will be added.     */    pci_conf[0x40] = 0x41; /* Special device-specific BAR at 0x40 */    pci_conf[0x41] = 0x1f;    pci_conf[0x42] = 0x00;    pci_conf[0x43] = 0x00;    d->pm1_control = SCI_EN;    acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);#ifdef CONFIG_PASSTHROUGH    gpe_acpi_init();    php_slots_init();    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, d);#endif    register_savevm("piix4acpi", 0, 1, piix4acpi_save, piix4acpi_load, d);}

⌨️ 快捷键说明

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