qemu/hw/isa/lpc_ich9.c
<<
>>
Prefs
   1/*
   2 * QEMU ICH9 Emulation
   3 *
   4 * Copyright (c) 2006 Fabrice Bellard
   5 * Copyright (c) 2009, 2010, 2011
   6 *               Isaku Yamahata <yamahata at valinux co jp>
   7 *               VA Linux Systems Japan K.K.
   8 * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
   9 *
  10 * This is based on piix.c, but heavily modified.
  11 *
  12 * Permission is hereby granted, free of charge, to any person obtaining a copy
  13 * of this software and associated documentation files (the "Software"), to deal
  14 * in the Software without restriction, including without limitation the rights
  15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16 * copies of the Software, and to permit persons to whom the Software is
  17 * furnished to do so, subject to the following conditions:
  18 *
  19 * The above copyright notice and this permission notice shall be included in
  20 * all copies or substantial portions of the Software.
  21 *
  22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28 * THE SOFTWARE.
  29 */
  30#include "qemu/osdep.h"
  31#include "qemu-common.h"
  32#include "cpu.h"
  33#include "hw/hw.h"
  34#include "qapi/visitor.h"
  35#include "qemu/range.h"
  36#include "hw/isa/isa.h"
  37#include "hw/sysbus.h"
  38#include "hw/i386/pc.h"
  39#include "hw/isa/apm.h"
  40#include "hw/i386/ioapic.h"
  41#include "hw/pci/pci.h"
  42#include "hw/pci/pcie_host.h"
  43#include "hw/pci/pci_bridge.h"
  44#include "hw/i386/ich9.h"
  45#include "hw/acpi/acpi.h"
  46#include "hw/acpi/ich9.h"
  47#include "hw/pci/pci_bus.h"
  48#include "exec/address-spaces.h"
  49#include "sysemu/sysemu.h"
  50
  51static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
  52
  53/*****************************************************************************/
  54/* ICH9 LPC PCI to ISA bridge */
  55
  56static void ich9_lpc_reset(DeviceState *qdev);
  57
  58/* chipset configuration register
  59 * to access chipset configuration registers, pci_[sg]et_{byte, word, long}
  60 * are used.
  61 * Although it's not pci configuration space, it's little endian as Intel.
  62 */
  63
  64static void ich9_cc_update_ir(uint8_t irr[PCI_NUM_PINS], uint16_t ir)
  65{
  66    int intx;
  67    for (intx = 0; intx < PCI_NUM_PINS; intx++) {
  68        irr[intx] = (ir >> (intx * ICH9_CC_DIR_SHIFT)) & ICH9_CC_DIR_MASK;
  69    }
  70}
  71
  72static void ich9_cc_update(ICH9LPCState *lpc)
  73{
  74    int slot;
  75    int pci_intx;
  76
  77    const int reg_offsets[] = {
  78        ICH9_CC_D25IR,
  79        ICH9_CC_D26IR,
  80        ICH9_CC_D27IR,
  81        ICH9_CC_D28IR,
  82        ICH9_CC_D29IR,
  83        ICH9_CC_D30IR,
  84        ICH9_CC_D31IR,
  85    };
  86    const int *offset;
  87
  88    /* D{25 - 31}IR, but D30IR is read only to 0. */
  89    for (slot = 25, offset = reg_offsets; slot < 32; slot++, offset++) {
  90        if (slot == 30) {
  91            continue;
  92        }
  93        ich9_cc_update_ir(lpc->irr[slot],
  94                          pci_get_word(lpc->chip_config + *offset));
  95    }
  96
  97    /*
  98     * D30: DMI2PCI bridge
  99     * It is arbitrarily decided how INTx lines of PCI devicesbehind the bridge
 100     * are connected to pirq lines. Our choice is PIRQ[E-H].
 101     * INT[A-D] are connected to PIRQ[E-H]
 102     */
 103    for (pci_intx = 0; pci_intx < PCI_NUM_PINS; pci_intx++) {
 104        lpc->irr[30][pci_intx] = pci_intx + 4;
 105    }
 106}
 107
 108static void ich9_cc_init(ICH9LPCState *lpc)
 109{
 110    int slot;
 111    int intx;
 112
 113    /* the default irq routing is arbitrary as long as it matches with
 114     * acpi irq routing table.
 115     * The one that is incompatible with piix_pci(= bochs) one is
 116     * intentionally chosen to let the users know that the different
 117     * board is used.
 118     *
 119     * int[A-D] -> pirq[E-F]
 120     * avoid pirq A-D because they are used for pci express port
 121     */
 122    for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
 123        for (intx = 0; intx < PCI_NUM_PINS; intx++) {
 124            lpc->irr[slot][intx] = (slot + intx) % 4 + 4;
 125        }
 126    }
 127    ich9_cc_update(lpc);
 128}
 129
 130static void ich9_cc_reset(ICH9LPCState *lpc)
 131{
 132    uint8_t *c = lpc->chip_config;
 133
 134    memset(lpc->chip_config, 0, sizeof(lpc->chip_config));
 135
 136    pci_set_long(c + ICH9_CC_D31IR, ICH9_CC_DIR_DEFAULT);
 137    pci_set_long(c + ICH9_CC_D30IR, ICH9_CC_D30IR_DEFAULT);
 138    pci_set_long(c + ICH9_CC_D29IR, ICH9_CC_DIR_DEFAULT);
 139    pci_set_long(c + ICH9_CC_D28IR, ICH9_CC_DIR_DEFAULT);
 140    pci_set_long(c + ICH9_CC_D27IR, ICH9_CC_DIR_DEFAULT);
 141    pci_set_long(c + ICH9_CC_D26IR, ICH9_CC_DIR_DEFAULT);
 142    pci_set_long(c + ICH9_CC_D25IR, ICH9_CC_DIR_DEFAULT);
 143    pci_set_long(c + ICH9_CC_GCS, ICH9_CC_GCS_DEFAULT);
 144
 145    ich9_cc_update(lpc);
 146}
 147
 148static void ich9_cc_addr_len(uint64_t *addr, unsigned *len)
 149{
 150    *addr &= ICH9_CC_ADDR_MASK;
 151    if (*addr + *len >= ICH9_CC_SIZE) {
 152        *len = ICH9_CC_SIZE - *addr;
 153    }
 154}
 155
 156/* val: little endian */
 157static void ich9_cc_write(void *opaque, hwaddr addr,
 158                          uint64_t val, unsigned len)
 159{
 160    ICH9LPCState *lpc = (ICH9LPCState *)opaque;
 161
 162    ich9_cc_addr_len(&addr, &len);
 163    memcpy(lpc->chip_config + addr, &val, len);
 164    pci_bus_fire_intx_routing_notifier(lpc->d.bus);
 165    ich9_cc_update(lpc);
 166}
 167
 168/* return value: little endian */
 169static uint64_t ich9_cc_read(void *opaque, hwaddr addr,
 170                              unsigned len)
 171{
 172    ICH9LPCState *lpc = (ICH9LPCState *)opaque;
 173
 174    uint32_t val = 0;
 175    ich9_cc_addr_len(&addr, &len);
 176    memcpy(&val, lpc->chip_config + addr, len);
 177    return val;
 178}
 179
 180/* IRQ routing */
 181/* */
 182static void ich9_lpc_rout(uint8_t pirq_rout, int *pic_irq, int *pic_dis)
 183{
 184    *pic_irq = pirq_rout & ICH9_LPC_PIRQ_ROUT_MASK;
 185    *pic_dis = pirq_rout & ICH9_LPC_PIRQ_ROUT_IRQEN;
 186}
 187
 188static void ich9_lpc_pic_irq(ICH9LPCState *lpc, int pirq_num,
 189                             int *pic_irq, int *pic_dis)
 190{
 191    switch (pirq_num) {
 192    case 0 ... 3: /* A-D */
 193        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQA_ROUT + pirq_num],
 194                      pic_irq, pic_dis);
 195        return;
 196    case 4 ... 7: /* E-H */
 197        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQE_ROUT + (pirq_num - 4)],
 198                      pic_irq, pic_dis);
 199        return;
 200    default:
 201        break;
 202    }
 203    abort();
 204}
 205
 206/* pic_irq: i8254 irq 0-15 */
 207static void ich9_lpc_update_pic(ICH9LPCState *lpc, int pic_irq)
 208{
 209    int i, pic_level;
 210
 211    /* The pic level is the logical OR of all the PCI irqs mapped to it */
 212    pic_level = 0;
 213    for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
 214        int tmp_irq;
 215        int tmp_dis;
 216        ich9_lpc_pic_irq(lpc, i, &tmp_irq, &tmp_dis);
 217        if (!tmp_dis && pic_irq == tmp_irq) {
 218            pic_level |= pci_bus_get_irq_level(lpc->d.bus, i);
 219        }
 220    }
 221    if (pic_irq == ich9_lpc_sci_irq(lpc)) {
 222        pic_level |= lpc->sci_level;
 223    }
 224
 225    qemu_set_irq(lpc->pic[pic_irq], pic_level);
 226}
 227
 228/* pirq: pirq[A-H] 0-7*/
 229static void ich9_lpc_update_by_pirq(ICH9LPCState *lpc, int pirq)
 230{
 231    int pic_irq;
 232    int pic_dis;
 233
 234    ich9_lpc_pic_irq(lpc, pirq, &pic_irq, &pic_dis);
 235    assert(pic_irq < ICH9_LPC_PIC_NUM_PINS);
 236    if (pic_dis) {
 237        return;
 238    }
 239
 240    ich9_lpc_update_pic(lpc, pic_irq);
 241}
 242
 243/* APIC mode: GSIx: PIRQ[A-H] -> GSI 16, ... no pirq shares same APIC pins. */
 244static int ich9_pirq_to_gsi(int pirq)
 245{
 246    return pirq + ICH9_LPC_PIC_NUM_PINS;
 247}
 248
 249static int ich9_gsi_to_pirq(int gsi)
 250{
 251    return gsi - ICH9_LPC_PIC_NUM_PINS;
 252}
 253
 254static void ich9_lpc_update_apic(ICH9LPCState *lpc, int gsi)
 255{
 256    int level = 0;
 257
 258    if (gsi >= ICH9_LPC_PIC_NUM_PINS) {
 259        level |= pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
 260    }
 261    if (gsi == ich9_lpc_sci_irq(lpc)) {
 262        level |= lpc->sci_level;
 263    }
 264
 265    qemu_set_irq(lpc->ioapic[gsi], level);
 266}
 267
 268void ich9_lpc_set_irq(void *opaque, int pirq, int level)
 269{
 270    ICH9LPCState *lpc = opaque;
 271
 272    assert(0 <= pirq);
 273    assert(pirq < ICH9_LPC_NB_PIRQS);
 274
 275    ich9_lpc_update_apic(lpc, ich9_pirq_to_gsi(pirq));
 276    ich9_lpc_update_by_pirq(lpc, pirq);
 277}
 278
 279/* return the pirq number (PIRQ[A-H]:0-7) corresponding to
 280 * a given device irq pin.
 281 */
 282int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx)
 283{
 284    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
 285    PCIBus *pci_bus = PCI_BUS(bus);
 286    PCIDevice *lpc_pdev =
 287            pci_bus->devices[PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC)];
 288    ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pdev);
 289
 290    return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx];
 291}
 292
 293PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin)
 294{
 295    ICH9LPCState *lpc = opaque;
 296    PCIINTxRoute route;
 297    int pic_irq;
 298    int pic_dis;
 299
 300    assert(0 <= pirq_pin);
 301    assert(pirq_pin < ICH9_LPC_NB_PIRQS);
 302
 303    route.mode = PCI_INTX_ENABLED;
 304    ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis);
 305    if (!pic_dis) {
 306        if (pic_irq < ICH9_LPC_PIC_NUM_PINS) {
 307            route.irq = pic_irq;
 308        } else {
 309            route.mode = PCI_INTX_DISABLED;
 310            route.irq = -1;
 311        }
 312    } else {
 313        route.irq = ich9_pirq_to_gsi(pirq_pin);
 314    }
 315
 316    return route;
 317}
 318
 319void ich9_generate_smi(void)
 320{
 321    cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
 322}
 323
 324void ich9_generate_nmi(void)
 325{
 326    cpu_interrupt(first_cpu, CPU_INTERRUPT_NMI);
 327}
 328
 329static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
 330{
 331    switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
 332            ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK) {
 333    case ICH9_LPC_ACPI_CTRL_9:
 334        return 9;
 335    case ICH9_LPC_ACPI_CTRL_10:
 336        return 10;
 337    case ICH9_LPC_ACPI_CTRL_11:
 338        return 11;
 339    case ICH9_LPC_ACPI_CTRL_20:
 340        return 20;
 341    case ICH9_LPC_ACPI_CTRL_21:
 342        return 21;
 343    default:
 344        /* reserved */
 345        break;
 346    }
 347    return -1;
 348}
 349
 350static void ich9_set_sci(void *opaque, int irq_num, int level)
 351{
 352    ICH9LPCState *lpc = opaque;
 353    int irq;
 354
 355    assert(irq_num == 0);
 356    level = !!level;
 357    if (level == lpc->sci_level) {
 358        return;
 359    }
 360    lpc->sci_level = level;
 361
 362    irq = ich9_lpc_sci_irq(lpc);
 363    if (irq < 0) {
 364        return;
 365    }
 366
 367    ich9_lpc_update_apic(lpc, irq);
 368    if (irq < ICH9_LPC_PIC_NUM_PINS) {
 369        ich9_lpc_update_pic(lpc, irq);
 370    }
 371}
 372
 373void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled)
 374{
 375    ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
 376    qemu_irq sci_irq;
 377
 378    sci_irq = qemu_allocate_irq(ich9_set_sci, lpc, 0);
 379    ich9_pm_init(lpc_pci, &lpc->pm, smm_enabled, sci_irq);
 380    ich9_lpc_reset(&lpc->d.qdev);
 381}
 382
 383/* APM */
 384
 385static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 386{
 387    ICH9LPCState *lpc = arg;
 388
 389    /* ACPI specs 3.0, 4.7.2.5 */
 390    acpi_pm1_cnt_update(&lpc->pm.acpi_regs,
 391                        val == ICH9_APM_ACPI_ENABLE,
 392                        val == ICH9_APM_ACPI_DISABLE);
 393    if (val == ICH9_APM_ACPI_ENABLE || val == ICH9_APM_ACPI_DISABLE) {
 394        return;
 395    }
 396
 397    /* SMI_EN = PMBASE + 30. SMI control and enable register */
 398    if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
 399        cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI);
 400    }
 401}
 402
 403/* config:PMBASE */
 404static void
 405ich9_lpc_pmbase_update(ICH9LPCState *lpc)
 406{
 407    uint32_t pm_io_base = pci_get_long(lpc->d.config + ICH9_LPC_PMBASE);
 408    pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
 409
 410    ich9_pm_iospace_update(&lpc->pm, pm_io_base);
 411}
 412
 413/* config:RCBA */
 414static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rcba_old)
 415{
 416    uint32_t rcba = pci_get_long(lpc->d.config + ICH9_LPC_RCBA);
 417
 418    if (rcba_old & ICH9_LPC_RCBA_EN) {
 419        memory_region_del_subregion(get_system_memory(), &lpc->rcrb_mem);
 420    }
 421    if (rcba & ICH9_LPC_RCBA_EN) {
 422        memory_region_add_subregion_overlap(get_system_memory(),
 423                                            rcba & ICH9_LPC_RCBA_BA_MASK,
 424                                            &lpc->rcrb_mem, 1);
 425    }
 426}
 427
 428/* config:GEN_PMCON* */
 429static void
 430ich9_lpc_pmcon_update(ICH9LPCState *lpc)
 431{
 432    uint16_t gen_pmcon_1 = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1);
 433    uint16_t wmask;
 434
 435    if (gen_pmcon_1 & ICH9_LPC_GEN_PMCON_1_SMI_LOCK) {
 436        wmask = pci_get_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1);
 437        wmask &= ~ICH9_LPC_GEN_PMCON_1_SMI_LOCK;
 438        pci_set_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1, wmask);
 439        lpc->pm.smi_en_wmask &= ~1;
 440    }
 441}
 442
 443static int ich9_lpc_post_load(void *opaque, int version_id)
 444{
 445    ICH9LPCState *lpc = opaque;
 446
 447    ich9_lpc_pmbase_update(lpc);
 448    ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RCBA_EN */);
 449    ich9_lpc_pmcon_update(lpc);
 450    return 0;
 451}
 452
 453static void ich9_lpc_config_write(PCIDevice *d,
 454                                  uint32_t addr, uint32_t val, int len)
 455{
 456    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
 457    uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA);
 458
 459    pci_default_write_config(d, addr, val, len);
 460    if (ranges_overlap(addr, len, ICH9_LPC_PMBASE, 4)) {
 461        ich9_lpc_pmbase_update(lpc);
 462    }
 463    if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) {
 464        ich9_lpc_rcba_update(lpc, rcba_old);
 465    }
 466    if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) {
 467        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
 468    }
 469    if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
 470        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
 471    }
 472    if (ranges_overlap(addr, len, ICH9_LPC_GEN_PMCON_1, 8)) {
 473        ich9_lpc_pmcon_update(lpc);
 474    }
 475}
 476
 477static void ich9_lpc_reset(DeviceState *qdev)
 478{
 479    PCIDevice *d = PCI_DEVICE(qdev);
 480    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
 481    uint32_t rcba_old = pci_get_long(d->config + ICH9_LPC_RCBA);
 482    int i;
 483
 484    for (i = 0; i < 4; i++) {
 485        pci_set_byte(d->config + ICH9_LPC_PIRQA_ROUT + i,
 486                     ICH9_LPC_PIRQ_ROUT_DEFAULT);
 487    }
 488    for (i = 0; i < 4; i++) {
 489        pci_set_byte(d->config + ICH9_LPC_PIRQE_ROUT + i,
 490                     ICH9_LPC_PIRQ_ROUT_DEFAULT);
 491    }
 492    pci_set_byte(d->config + ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_DEFAULT);
 493
 494    pci_set_long(d->config + ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
 495    pci_set_long(d->config + ICH9_LPC_RCBA, ICH9_LPC_RCBA_DEFAULT);
 496
 497    ich9_cc_reset(lpc);
 498
 499    ich9_lpc_pmbase_update(lpc);
 500    ich9_lpc_rcba_update(lpc, rcba_old);
 501
 502    lpc->sci_level = 0;
 503    lpc->rst_cnt = 0;
 504}
 505
 506/* root complex register block is mapped into memory space */
 507static const MemoryRegionOps rcrb_mmio_ops = {
 508    .read = ich9_cc_read,
 509    .write = ich9_cc_write,
 510    .endianness = DEVICE_LITTLE_ENDIAN,
 511};
 512
 513static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
 514{
 515    ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready);
 516    MemoryRegion *io_as = pci_address_space_io(&s->d);
 517    uint8_t *pci_conf;
 518
 519    pci_conf = s->d.config;
 520    if (memory_region_present(io_as, 0x3f8)) {
 521        /* com1 */
 522        pci_conf[0x82] |= 0x01;
 523    }
 524    if (memory_region_present(io_as, 0x2f8)) {
 525        /* com2 */
 526        pci_conf[0x82] |= 0x02;
 527    }
 528    if (memory_region_present(io_as, 0x378)) {
 529        /* lpt */
 530        pci_conf[0x82] |= 0x04;
 531    }
 532    if (memory_region_present(io_as, 0x3f2)) {
 533        /* floppy */
 534        pci_conf[0x82] |= 0x08;
 535    }
 536}
 537
 538/* reset control */
 539static void ich9_rst_cnt_write(void *opaque, hwaddr addr, uint64_t val,
 540                               unsigned len)
 541{
 542    ICH9LPCState *lpc = opaque;
 543
 544    if (val & 4) {
 545        qemu_system_reset_request();
 546        return;
 547    }
 548    lpc->rst_cnt = val & 0xA; /* keep FULL_RST (bit 3) and SYS_RST (bit 1) */
 549}
 550
 551static uint64_t ich9_rst_cnt_read(void *opaque, hwaddr addr, unsigned len)
 552{
 553    ICH9LPCState *lpc = opaque;
 554
 555    return lpc->rst_cnt;
 556}
 557
 558static const MemoryRegionOps ich9_rst_cnt_ops = {
 559    .read = ich9_rst_cnt_read,
 560    .write = ich9_rst_cnt_write,
 561    .endianness = DEVICE_LITTLE_ENDIAN
 562};
 563
 564Object *ich9_lpc_find(void)
 565{
 566    bool ambig;
 567    Object *o = object_resolve_path_type("", TYPE_ICH9_LPC_DEVICE, &ambig);
 568
 569    if (ambig) {
 570        return NULL;
 571    }
 572    return o;
 573}
 574
 575static void ich9_lpc_get_sci_int(Object *obj, Visitor *v, const char *name,
 576                                 void *opaque, Error **errp)
 577{
 578    ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
 579    uint32_t value = ich9_lpc_sci_irq(lpc);
 580
 581    visit_type_uint32(v, name, &value, errp);
 582}
 583
 584static void ich9_lpc_add_properties(ICH9LPCState *lpc)
 585{
 586    static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
 587    static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
 588
 589    object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32",
 590                        ich9_lpc_get_sci_int,
 591                        NULL, NULL, NULL, NULL);
 592    object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
 593                                  &acpi_enable_cmd, NULL);
 594    object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD,
 595                                  &acpi_disable_cmd, NULL);
 596
 597    ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL);
 598}
 599
 600static void ich9_lpc_initfn(Object *obj)
 601{
 602    ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
 603
 604    ich9_lpc_add_properties(lpc);
 605}
 606
 607static void ich9_lpc_realize(PCIDevice *d, Error **errp)
 608{
 609    ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
 610    ISABus *isa_bus;
 611
 612    isa_bus = isa_bus_new(DEVICE(d), get_system_memory(), get_system_io(),
 613                          errp);
 614    if (!isa_bus) {
 615        return;
 616    }
 617
 618    pci_set_long(d->wmask + ICH9_LPC_PMBASE,
 619                 ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
 620
 621    memory_region_init_io(&lpc->rcrb_mem, OBJECT(d), &rcrb_mmio_ops, lpc,
 622                          "lpc-rcrb-mmio", ICH9_CC_SIZE);
 623
 624    lpc->isa_bus = isa_bus;
 625
 626    ich9_cc_init(lpc);
 627    apm_init(d, &lpc->apm, ich9_apm_ctrl_changed, lpc);
 628
 629    lpc->machine_ready.notify = ich9_lpc_machine_ready;
 630    qemu_add_machine_init_done_notifier(&lpc->machine_ready);
 631
 632    memory_region_init_io(&lpc->rst_cnt_mem, OBJECT(d), &ich9_rst_cnt_ops, lpc,
 633                          "lpc-reset-control", 1);
 634    memory_region_add_subregion_overlap(pci_address_space_io(d),
 635                                        ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
 636                                        1);
 637}
 638
 639static void ich9_device_plug_cb(HotplugHandler *hotplug_dev,
 640                                DeviceState *dev, Error **errp)
 641{
 642    ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
 643
 644    ich9_pm_device_plug_cb(&lpc->pm, dev, errp);
 645}
 646
 647static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev,
 648                                          DeviceState *dev, Error **errp)
 649{
 650    ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
 651
 652    ich9_pm_device_unplug_request_cb(&lpc->pm, dev, errp);
 653}
 654
 655static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev,
 656                                  DeviceState *dev, Error **errp)
 657{
 658    ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
 659
 660    ich9_pm_device_unplug_cb(&lpc->pm, dev, errp);
 661}
 662
 663static bool ich9_rst_cnt_needed(void *opaque)
 664{
 665    ICH9LPCState *lpc = opaque;
 666
 667    return (lpc->rst_cnt != 0);
 668}
 669
 670static const VMStateDescription vmstate_ich9_rst_cnt = {
 671    .name = "ICH9LPC/rst_cnt",
 672    .version_id = 1,
 673    .minimum_version_id = 1,
 674    .needed = ich9_rst_cnt_needed,
 675    .fields = (VMStateField[]) {
 676        VMSTATE_UINT8(rst_cnt, ICH9LPCState),
 677        VMSTATE_END_OF_LIST()
 678    }
 679};
 680
 681static const VMStateDescription vmstate_ich9_lpc = {
 682    .name = "ICH9LPC",
 683    .version_id = 1,
 684    .minimum_version_id = 1,
 685    .post_load = ich9_lpc_post_load,
 686    .fields = (VMStateField[]) {
 687        VMSTATE_PCI_DEVICE(d, ICH9LPCState),
 688        VMSTATE_STRUCT(apm, ICH9LPCState, 0, vmstate_apm, APMState),
 689        VMSTATE_STRUCT(pm, ICH9LPCState, 0, vmstate_ich9_pm, ICH9LPCPMRegs),
 690        VMSTATE_UINT8_ARRAY(chip_config, ICH9LPCState, ICH9_CC_SIZE),
 691        VMSTATE_UINT32(sci_level, ICH9LPCState),
 692        VMSTATE_END_OF_LIST()
 693    },
 694    .subsections = (const VMStateDescription*[]) {
 695        &vmstate_ich9_rst_cnt,
 696        NULL
 697    }
 698};
 699
 700static Property ich9_lpc_properties[] = {
 701    DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true),
 702    DEFINE_PROP_END_OF_LIST(),
 703};
 704
 705static void ich9_lpc_class_init(ObjectClass *klass, void *data)
 706{
 707    DeviceClass *dc = DEVICE_CLASS(klass);
 708    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 709    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
 710    AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass);
 711
 712    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 713    dc->reset = ich9_lpc_reset;
 714    k->realize = ich9_lpc_realize;
 715    dc->vmsd = &vmstate_ich9_lpc;
 716    dc->props = ich9_lpc_properties;
 717    k->config_write = ich9_lpc_config_write;
 718    dc->desc = "ICH9 LPC bridge";
 719    k->vendor_id = PCI_VENDOR_ID_INTEL;
 720    k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8;
 721    k->revision = ICH9_A2_LPC_REVISION;
 722    k->class_id = PCI_CLASS_BRIDGE_ISA;
 723    /*
 724     * Reason: part of ICH9 southbridge, needs to be wired up by
 725     * pc_q35_init()
 726     */
 727    dc->cannot_instantiate_with_device_add_yet = true;
 728    hc->plug = ich9_device_plug_cb;
 729    hc->unplug_request = ich9_device_unplug_request_cb;
 730    hc->unplug = ich9_device_unplug_cb;
 731    adevc->ospm_status = ich9_pm_ospm_status;
 732}
 733
 734static const TypeInfo ich9_lpc_info = {
 735    .name       = TYPE_ICH9_LPC_DEVICE,
 736    .parent     = TYPE_PCI_DEVICE,
 737    .instance_size = sizeof(struct ICH9LPCState),
 738    .instance_init = ich9_lpc_initfn,
 739    .class_init  = ich9_lpc_class_init,
 740    .interfaces = (InterfaceInfo[]) {
 741        { TYPE_HOTPLUG_HANDLER },
 742        { TYPE_ACPI_DEVICE_IF },
 743        { }
 744    }
 745};
 746
 747static void ich9_lpc_register(void)
 748{
 749    type_register_static(&ich9_lpc_info);
 750}
 751
 752type_init(ich9_lpc_register);
 753