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

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

unix.superglobalmegacorp.com

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