Annotation of qemu/hw/acpi_piix4.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ACPI implementation
                      3:  *
                      4:  * Copyright (c) 2006 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License version 2 as published by the Free Software Foundation.
                      9:  *
                     10:  * This library is distributed in the hope that it will be useful,
                     11:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     13:  * Lesser General Public License for more details.
                     14:  *
                     15:  * You should have received a copy of the GNU Lesser General Public
                     16:  * License along with this library; if not, see <http://www.gnu.org/licenses/>
                     17:  */
                     18: #include "hw.h"
                     19: #include "pc.h"
                     20: #include "apm.h"
                     21: #include "pm_smbus.h"
                     22: #include "pci.h"
                     23: #include "acpi.h"
                     24: #include "sysemu.h"
                     25: 
                     26: //#define DEBUG
                     27: 
                     28: #ifdef DEBUG
                     29: # define PIIX4_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
                     30: #else
                     31: # define PIIX4_DPRINTF(format, ...)     do { } while (0)
                     32: #endif
                     33: 
                     34: #define ACPI_DBG_IO_ADDR  0xb044
                     35: 
                     36: #define GPE_BASE 0xafe0
                     37: #define PCI_BASE 0xae00
                     38: #define PCI_EJ_BASE 0xae08
                     39: 
                     40: struct gpe_regs {
                     41:     uint16_t sts; /* status */
                     42:     uint16_t en;  /* enabled */
                     43: };
                     44: 
                     45: struct pci_status {
                     46:     uint32_t up;
                     47:     uint32_t down;
                     48: };
                     49: 
                     50: typedef struct PIIX4PMState {
                     51:     PCIDevice dev;
                     52:     uint16_t pmsts;
                     53:     uint16_t pmen;
                     54:     uint16_t pmcntrl;
                     55: 
                     56:     APMState apm;
                     57: 
                     58:     QEMUTimer *tmr_timer;
                     59:     int64_t tmr_overflow_time;
                     60: 
                     61:     PMSMBus smb;
                     62:     uint32_t smb_io_base;
                     63: 
                     64:     qemu_irq irq;
                     65:     qemu_irq cmos_s3;
                     66:     qemu_irq smi_irq;
                     67:     int kvm_enabled;
                     68: 
                     69:     /* for pci hotplug */
                     70:     struct gpe_regs gpe;
                     71:     struct pci_status pci0_status;
                     72: } PIIX4PMState;
                     73: 
                     74: static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
                     75: 
                     76: #define ACPI_ENABLE 0xf1
                     77: #define ACPI_DISABLE 0xf0
                     78: 
                     79: static uint32_t get_pmtmr(PIIX4PMState *s)
                     80: {
                     81:     uint32_t d;
                     82:     d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
                     83:     return d & 0xffffff;
                     84: }
                     85: 
                     86: static int get_pmsts(PIIX4PMState *s)
                     87: {
                     88:     int64_t d;
                     89: 
                     90:     d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
                     91:                  get_ticks_per_sec());
                     92:     if (d >= s->tmr_overflow_time)
                     93:         s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
                     94:     return s->pmsts;
                     95: }
                     96: 
                     97: static void pm_update_sci(PIIX4PMState *s)
                     98: {
                     99:     int sci_level, pmsts;
                    100:     int64_t expire_time;
                    101: 
                    102:     pmsts = get_pmsts(s);
                    103:     sci_level = (((pmsts & s->pmen) &
                    104:                   (ACPI_BITMASK_RT_CLOCK_ENABLE |
                    105:                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    106:                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    107:                    ACPI_BITMASK_TIMER_ENABLE)) != 0);
                    108:     qemu_set_irq(s->irq, sci_level);
                    109:     /* schedule a timer interruption if needed */
                    110:     if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
                    111:         !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
                    112:         expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
                    113:                                PM_TIMER_FREQUENCY);
                    114:         qemu_mod_timer(s->tmr_timer, expire_time);
                    115:     } else {
                    116:         qemu_del_timer(s->tmr_timer);
                    117:     }
                    118: }
                    119: 
                    120: static void pm_tmr_timer(void *opaque)
                    121: {
                    122:     PIIX4PMState *s = opaque;
                    123:     pm_update_sci(s);
                    124: }
                    125: 
                    126: static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                    127: {
                    128:     PIIX4PMState *s = opaque;
                    129:     addr &= 0x3f;
                    130:     switch(addr) {
                    131:     case 0x00:
                    132:         {
                    133:             int64_t d;
                    134:             int pmsts;
                    135:             pmsts = get_pmsts(s);
                    136:             if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
                    137:                 /* if TMRSTS is reset, then compute the new overflow time */
                    138:                 d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
                    139:                              get_ticks_per_sec());
                    140:                 s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
                    141:             }
                    142:             s->pmsts &= ~val;
                    143:             pm_update_sci(s);
                    144:         }
                    145:         break;
                    146:     case 0x02:
                    147:         s->pmen = val;
                    148:         pm_update_sci(s);
                    149:         break;
                    150:     case 0x04:
                    151:         {
                    152:             int sus_typ;
                    153:             s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
                    154:             if (val & ACPI_BITMASK_SLEEP_ENABLE) {
                    155:                 /* change suspend type */
                    156:                 sus_typ = (val >> 10) & 7;
                    157:                 switch(sus_typ) {
                    158:                 case 0: /* soft power off */
                    159:                     qemu_system_shutdown_request();
                    160:                     break;
                    161:                 case 1:
                    162:                     /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
                    163:                        Pretend that resume was caused by power button */
                    164:                     s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
                    165:                                  ACPI_BITMASK_POWER_BUTTON_STATUS);
                    166:                     qemu_system_reset_request();
                    167:                     if (s->cmos_s3) {
                    168:                         qemu_irq_raise(s->cmos_s3);
                    169:                     }
                    170:                 default:
                    171:                     break;
                    172:                 }
                    173:             }
                    174:         }
                    175:         break;
                    176:     default:
                    177:         break;
                    178:     }
                    179:     PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val);
                    180: }
                    181: 
                    182: static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
                    183: {
                    184:     PIIX4PMState *s = opaque;
                    185:     uint32_t val;
                    186: 
                    187:     addr &= 0x3f;
                    188:     switch(addr) {
                    189:     case 0x00:
                    190:         val = get_pmsts(s);
                    191:         break;
                    192:     case 0x02:
                    193:         val = s->pmen;
                    194:         break;
                    195:     case 0x04:
                    196:         val = s->pmcntrl;
                    197:         break;
                    198:     default:
                    199:         val = 0;
                    200:         break;
                    201:     }
                    202:     PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
                    203:     return val;
                    204: }
                    205: 
                    206: static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
                    207: {
                    208:     //    PIIX4PMState *s = opaque;
                    209:     PIIX4_DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr & 0x3f, val);
                    210: }
                    211: 
                    212: static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
                    213: {
                    214:     PIIX4PMState *s = opaque;
                    215:     uint32_t val;
                    216: 
                    217:     addr &= 0x3f;
                    218:     switch(addr) {
                    219:     case 0x08:
                    220:         val = get_pmtmr(s);
                    221:         break;
                    222:     default:
                    223:         val = 0;
                    224:         break;
                    225:     }
                    226:     PIIX4_DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
                    227:     return val;
                    228: }
                    229: 
                    230: static void apm_ctrl_changed(uint32_t val, void *arg)
                    231: {
                    232:     PIIX4PMState *s = arg;
                    233: 
                    234:     /* ACPI specs 3.0, 4.7.2.5 */
                    235:     if (val == ACPI_ENABLE) {
                    236:         s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
                    237:     } else if (val == ACPI_DISABLE) {
                    238:         s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
                    239:     }
                    240: 
                    241:     if (s->dev.config[0x5b] & (1 << 1)) {
                    242:         if (s->smi_irq) {
                    243:             qemu_irq_raise(s->smi_irq);
                    244:         }
                    245:     }
                    246: }
                    247: 
                    248: static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
                    249: {
                    250:     PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val);
                    251: }
                    252: 
                    253: static void pm_io_space_update(PIIX4PMState *s)
                    254: {
                    255:     uint32_t pm_io_base;
                    256: 
                    257:     if (s->dev.config[0x80] & 1) {
                    258:         pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
                    259:         pm_io_base &= 0xffc0;
                    260: 
                    261:         /* XXX: need to improve memory and ioport allocation */
                    262:         PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
                    263:         register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
                    264:         register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
                    265:         register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
                    266:         register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
                    267:     }
                    268: }
                    269: 
                    270: static void pm_write_config(PCIDevice *d,
                    271:                             uint32_t address, uint32_t val, int len)
                    272: {
                    273:     pci_default_write_config(d, address, val, len);
                    274:     if (range_covers_byte(address, len, 0x80))
                    275:         pm_io_space_update((PIIX4PMState *)d);
                    276: }
                    277: 
                    278: static int vmstate_acpi_post_load(void *opaque, int version_id)
                    279: {
                    280:     PIIX4PMState *s = opaque;
                    281: 
                    282:     pm_io_space_update(s);
                    283:     return 0;
                    284: }
                    285: 
                    286: static const VMStateDescription vmstate_gpe = {
                    287:     .name = "gpe",
                    288:     .version_id = 1,
                    289:     .minimum_version_id = 1,
                    290:     .minimum_version_id_old = 1,
                    291:     .fields      = (VMStateField []) {
                    292:         VMSTATE_UINT16(sts, struct gpe_regs),
                    293:         VMSTATE_UINT16(en, struct gpe_regs),
                    294:         VMSTATE_END_OF_LIST()
                    295:     }
                    296: };
                    297: 
                    298: static const VMStateDescription vmstate_pci_status = {
                    299:     .name = "pci_status",
                    300:     .version_id = 1,
                    301:     .minimum_version_id = 1,
                    302:     .minimum_version_id_old = 1,
                    303:     .fields      = (VMStateField []) {
                    304:         VMSTATE_UINT32(up, struct pci_status),
                    305:         VMSTATE_UINT32(down, struct pci_status),
                    306:         VMSTATE_END_OF_LIST()
                    307:     }
                    308: };
                    309: 
                    310: static const VMStateDescription vmstate_acpi = {
                    311:     .name = "piix4_pm",
                    312:     .version_id = 2,
                    313:     .minimum_version_id = 1,
                    314:     .minimum_version_id_old = 1,
                    315:     .post_load = vmstate_acpi_post_load,
                    316:     .fields      = (VMStateField []) {
                    317:         VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
                    318:         VMSTATE_UINT16(pmsts, PIIX4PMState),
                    319:         VMSTATE_UINT16(pmen, PIIX4PMState),
                    320:         VMSTATE_UINT16(pmcntrl, PIIX4PMState),
                    321:         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
                    322:         VMSTATE_TIMER(tmr_timer, PIIX4PMState),
                    323:         VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
                    324:         VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
                    325:         VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
                    326:                        struct pci_status),
                    327:         VMSTATE_END_OF_LIST()
                    328:     }
                    329: };
                    330: 
                    331: static void piix4_reset(void *opaque)
                    332: {
                    333:     PIIX4PMState *s = opaque;
                    334:     uint8_t *pci_conf = s->dev.config;
                    335: 
                    336:     pci_conf[0x58] = 0;
                    337:     pci_conf[0x59] = 0;
                    338:     pci_conf[0x5a] = 0;
                    339:     pci_conf[0x5b] = 0;
                    340: 
                    341:     if (s->kvm_enabled) {
                    342:         /* Mark SMM as already inited (until KVM supports SMM). */
                    343:         pci_conf[0x5B] = 0x02;
                    344:     }
                    345: }
                    346: 
                    347: static void piix4_powerdown(void *opaque, int irq, int power_failing)
                    348: {
                    349:     PIIX4PMState *s = opaque;
                    350: 
                    351:     if (!s) {
                    352:         qemu_system_shutdown_request();
                    353:     } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
                    354:         s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
                    355:         pm_update_sci(s);
                    356:     }
                    357: }
                    358: 
                    359: static int piix4_pm_initfn(PCIDevice *dev)
                    360: {
                    361:     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
                    362:     uint8_t *pci_conf;
                    363: 
                    364:     pci_conf = s->dev.config;
                    365:     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
                    366:     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
                    367:     pci_conf[0x06] = 0x80;
                    368:     pci_conf[0x07] = 0x02;
                    369:     pci_conf[0x08] = 0x03; // revision number
                    370:     pci_conf[0x09] = 0x00;
                    371:     pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
                    372:     pci_conf[0x3d] = 0x01; // interrupt pin 1
                    373: 
                    374:     pci_conf[0x40] = 0x01; /* PM io base read only bit */
                    375: 
                    376:     /* APM */
                    377:     apm_init(&s->apm, apm_ctrl_changed, s);
                    378: 
                    379:     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
                    380: 
                    381:     if (s->kvm_enabled) {
                    382:         /* Mark SMM as already inited to prevent SMM from running.  KVM does not
                    383:          * support SMM mode. */
                    384:         pci_conf[0x5B] = 0x02;
                    385:     }
                    386: 
                    387:     /* XXX: which specification is used ? The i82731AB has different
                    388:        mappings */
                    389:     pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
                    390:     pci_conf[0x63] = 0x60;
                    391:     pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
                    392:        (serial_hds[1] != NULL ? 0x90 : 0);
                    393: 
                    394:     pci_conf[0x90] = s->smb_io_base | 1;
                    395:     pci_conf[0x91] = s->smb_io_base >> 8;
                    396:     pci_conf[0xd2] = 0x09;
                    397:     register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
                    398:     register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
                    399: 
                    400:     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
                    401: 
                    402:     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
                    403: 
                    404:     pm_smbus_init(&s->dev.qdev, &s->smb);
                    405:     qemu_register_reset(piix4_reset, s);
                    406:     piix4_acpi_system_hot_add_init(dev->bus, s);
                    407: 
                    408:     return 0;
                    409: }
                    410: 
                    411: i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                    412:                        qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
                    413:                        int kvm_enabled)
                    414: {
                    415:     PCIDevice *dev;
                    416:     PIIX4PMState *s;
                    417: 
                    418:     dev = pci_create(bus, devfn, "PIIX4_PM");
                    419:     qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base);
                    420: 
                    421:     s = DO_UPCAST(PIIX4PMState, dev, dev);
                    422:     s->irq = sci_irq;
                    423:     s->cmos_s3 = cmos_s3;
                    424:     s->smi_irq = smi_irq;
                    425:     s->kvm_enabled = kvm_enabled;
                    426: 
                    427:     qdev_init_nofail(&dev->qdev);
                    428: 
                    429:     return s->smb.smbus;
                    430: }
                    431: 
                    432: static PCIDeviceInfo piix4_pm_info = {
                    433:     .qdev.name          = "PIIX4_PM",
                    434:     .qdev.desc          = "PM",
                    435:     .qdev.size          = sizeof(PIIX4PMState),
                    436:     .qdev.vmsd          = &vmstate_acpi,
                    437:     .init               = piix4_pm_initfn,
                    438:     .config_write       = pm_write_config,
                    439:     .qdev.props         = (Property[]) {
                    440:         DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
                    441:         DEFINE_PROP_END_OF_LIST(),
                    442:     }
                    443: };
                    444: 
                    445: static void piix4_pm_register(void)
                    446: {
                    447:     pci_qdev_register(&piix4_pm_info);
                    448: }
                    449: 
                    450: device_init(piix4_pm_register);
                    451: 
                    452: static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
                    453: {
                    454:     if (addr & 1)
                    455:         return (val >> 8) & 0xff;
                    456:     return val & 0xff;
                    457: }
                    458: 
                    459: static uint32_t gpe_readb(void *opaque, uint32_t addr)
                    460: {
                    461:     uint32_t val = 0;
                    462:     struct gpe_regs *g = opaque;
                    463:     switch (addr) {
                    464:         case GPE_BASE:
                    465:         case GPE_BASE + 1:
                    466:             val = gpe_read_val(g->sts, addr);
                    467:             break;
                    468:         case GPE_BASE + 2:
                    469:         case GPE_BASE + 3:
                    470:             val = gpe_read_val(g->en, addr);
                    471:             break;
                    472:         default:
                    473:             break;
                    474:     }
                    475: 
                    476:     PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
                    477:     return val;
                    478: }
                    479: 
                    480: static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
                    481: {
                    482:     if (addr & 1)
                    483:         *cur = (*cur & 0xff) | (val << 8);
                    484:     else
                    485:         *cur = (*cur & 0xff00) | (val & 0xff);
                    486: }
                    487: 
                    488: static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
                    489: {
                    490:     uint16_t x1, x0 = val & 0xff;
                    491:     int shift = (addr & 1) ? 8 : 0;
                    492: 
                    493:     x1 = (*cur >> shift) & 0xff;
                    494: 
                    495:     x1 = x1 & ~x0;
                    496: 
                    497:     *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
                    498: }
                    499: 
                    500: static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
                    501: {
                    502:     struct gpe_regs *g = opaque;
                    503:     switch (addr) {
                    504:         case GPE_BASE:
                    505:         case GPE_BASE + 1:
                    506:             gpe_reset_val(&g->sts, addr, val);
                    507:             break;
                    508:         case GPE_BASE + 2:
                    509:         case GPE_BASE + 3:
                    510:             gpe_write_val(&g->en, addr, val);
                    511:             break;
                    512:         default:
                    513:             break;
                    514:    }
                    515: 
                    516:     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
                    517: }
                    518: 
                    519: static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
                    520: {
                    521:     uint32_t val = 0;
                    522:     struct pci_status *g = opaque;
                    523:     switch (addr) {
                    524:         case PCI_BASE:
                    525:             val = g->up;
                    526:             break;
                    527:         case PCI_BASE + 4:
                    528:             val = g->down;
                    529:             break;
                    530:         default:
                    531:             break;
                    532:     }
                    533: 
                    534:     PIIX4_DPRINTF("pcihotplug read %x == %x\n", addr, val);
                    535:     return val;
                    536: }
                    537: 
                    538: static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
                    539: {
                    540:     struct pci_status *g = opaque;
                    541:     switch (addr) {
                    542:         case PCI_BASE:
                    543:             g->up = val;
                    544:             break;
                    545:         case PCI_BASE + 4:
                    546:             g->down = val;
                    547:             break;
                    548:    }
                    549: 
                    550:     PIIX4_DPRINTF("pcihotplug write %x <== %d\n", addr, val);
                    551: }
                    552: 
                    553: static uint32_t pciej_read(void *opaque, uint32_t addr)
                    554: {
                    555:     PIIX4_DPRINTF("pciej read %x\n", addr);
                    556:     return 0;
                    557: }
                    558: 
                    559: static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
                    560: {
                    561:     BusState *bus = opaque;
                    562:     DeviceState *qdev, *next;
                    563:     PCIDevice *dev;
                    564:     int slot = ffs(val) - 1;
                    565: 
                    566:     QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
                    567:         dev = DO_UPCAST(PCIDevice, qdev, qdev);
                    568:         if (PCI_SLOT(dev->devfn) == slot) {
                    569:             qdev_free(qdev);
                    570:         }
                    571:     }
                    572: 
                    573: 
                    574:     PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
                    575: }
                    576: 
                    577: static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state);
                    578: 
                    579: static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
                    580: {
                    581:     struct gpe_regs *gpe = &s->gpe;
                    582:     struct pci_status *pci0_status = &s->pci0_status;
                    583: 
                    584:     register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, gpe);
                    585:     register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, gpe);
                    586: 
                    587:     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
                    588:     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
                    589: 
                    590:     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
                    591:     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
                    592: 
                    593:     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
                    594: }
                    595: 
                    596: static void enable_device(PIIX4PMState *s, int slot)
                    597: {
                    598:     s->gpe.sts |= 2;
                    599:     s->pci0_status.up |= (1 << slot);
                    600: }
                    601: 
                    602: static void disable_device(PIIX4PMState *s, int slot)
                    603: {
                    604:     s->gpe.sts |= 2;
                    605:     s->pci0_status.down |= (1 << slot);
                    606: }
                    607: 
                    608: static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state)
                    609: {
                    610:     int slot = PCI_SLOT(dev->devfn);
                    611:     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
                    612:                                 DO_UPCAST(PCIDevice, qdev, qdev));
                    613: 
                    614:     s->pci0_status.up = 0;
                    615:     s->pci0_status.down = 0;
                    616:     if (state) {
                    617:         enable_device(s, slot);
                    618:     } else {
                    619:         disable_device(s, slot);
                    620:     }
                    621:     if (s->gpe.en & 2) {
                    622:         qemu_set_irq(s->irq, 1);
                    623:         qemu_set_irq(s->irq, 0);
                    624:     }
                    625:     return 0;
                    626: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.