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