Revision ac0cdda3 hw/pcie.c

b/hw/pcie.c
19 19
 */
20 20

  
21 21
#include "sysemu.h"
22
#include "range.h"
22 23
#include "pci_bridge.h"
23 24
#include "pcie.h"
24 25
#include "msix.h"
......
296 297
    uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
297 298
    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
298 299

  
300
    if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) {
301
        return;
302
    }
303

  
299 304
    PCIE_DEV_PRINTF(dev,
300 305
                    "addr: 0x%"PRIx32" val: 0x%"PRIx32" len: %d\n"
301 306
                    "\tsltctl_prev: 0x%02"PRIx16" sltctl: 0x%02"PRIx16
......
303 308
                    addr, val, len, sltctl_prev, sltctl, sltsta);
304 309

  
305 310
    /* SLTCTL */
306
    if (ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) {
307
        PCIE_DEV_PRINTF(dev, "sltctl: 0x%02"PRIx16" -> 0x%02"PRIx16"\n",
308
                        sltctl_prev, sltctl);
309
        if (pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
310
                                         PCI_EXP_SLTCTL_EIC)) {
311
            sltsta ^= PCI_EXP_SLTSTA_EIS; /* toggle PCI_EXP_SLTSTA_EIS bit */
312
            pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
313
            PCIE_DEV_PRINTF(dev, "PCI_EXP_SLTCTL_EIC: "
314
                            "sltsta -> 0x%02"PRIx16"\n",
315
                            sltsta);
316
        }
317

  
318
        /*
319
         * The events control bits might be enabled or disabled,
320
         * Check if the software notificastion condition is satisfied
321
         * or disatisfied.
322
         *
323
         * 6.7.3.4 Software Notification of Hot-plug events
324
         */
325
        if (pci_msi_enabled(dev)) {
326
            bool msi_trigger =
327
                (sltctl & PCI_EXP_SLTCTL_HPIE) &&
328
                ((sltctl_prev ^ sltctl) & sltctl & /* stlctl: 0 -> 1 */
329
                 sltsta & PCI_EXP_HP_EV_SUPPORTED);
330
            if (msi_trigger) {
331
                pci_msi_notify(dev, pcie_cap_flags_get_vector(dev));
332
            }
333
        } else {
334
            int int_level =
335
                (sltctl & PCI_EXP_SLTCTL_HPIE) &&
336
                (sltctl & sltsta & PCI_EXP_HP_EV_SUPPORTED);
337
            qemu_set_irq(dev->irq[dev->exp.hpev_intx], int_level);
338
        }
311
    PCIE_DEV_PRINTF(dev, "sltctl: 0x%02"PRIx16" -> 0x%02"PRIx16"\n",
312
                    sltctl_prev, sltctl);
313

  
314
    if (pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
315
                                     PCI_EXP_SLTCTL_EIC)) {
316
        sltsta ^= PCI_EXP_SLTSTA_EIS; /* toggle PCI_EXP_SLTSTA_EIS bit */
317
        pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
318
        PCIE_DEV_PRINTF(dev, "PCI_EXP_SLTCTL_EIC: "
319
                        "sltsta -> 0x%02"PRIx16"\n",
320
                        sltsta);
321
    }
339 322

  
340
        if (!((sltctl_prev ^ sltctl) & PCI_EXP_SLTCTL_SUPPORTED)) {
341
            PCIE_DEV_PRINTF(dev,
342
                            "sprious command completion slctl "
343
                            "0x%"PRIx16" -> 0x%"PRIx16"\n",
344
                            sltctl_prev, sltctl);
323
    /*
324
     * The events control bits might be enabled or disabled,
325
     * Check if the software notificastion condition is satisfied
326
     * or disatisfied.
327
     *
328
     * 6.7.3.4 Software Notification of Hot-plug events
329
     */
330
    if (pci_msi_enabled(dev)) {
331
        bool msi_trigger =
332
            (sltctl & PCI_EXP_SLTCTL_HPIE) &&
333
            ((sltctl_prev ^ sltctl) & sltctl & /* stlctl: 0 -> 1 */
334
             sltsta & PCI_EXP_HP_EV_SUPPORTED);
335
        if (msi_trigger) {
336
            pci_msi_notify(dev, pcie_cap_flags_get_vector(dev));
345 337
        }
338
    } else {
339
        int int_level =
340
            (sltctl & PCI_EXP_SLTCTL_HPIE) &&
341
            (sltctl & sltsta & PCI_EXP_HP_EV_SUPPORTED);
342
        qemu_set_irq(dev->irq[dev->exp.hpev_intx], int_level);
343
    }
346 344

  
347
        /* command completion.
348
         * Real hardware might take a while to complete
349
         * requested command because physical movement would be involved
350
         * like locking the electromechanical lock.
351
         * However in our case, command is completed instantaneously above,
352
         * so send a command completion event right now.
353
         *
354
         * 6.7.3.2 Command Completed Events
355
         */
356
        /* set command completed bit */
357
        pcie_cap_slot_event(dev, PCI_EXP_HP_EV_CCI);
345
    if (!((sltctl_prev ^ sltctl) & PCI_EXP_SLTCTL_SUPPORTED)) {
346
        PCIE_DEV_PRINTF(dev,
347
                        "sprious command completion slctl "
348
                        "0x%"PRIx16" -> 0x%"PRIx16"\n",
349
                        sltctl_prev, sltctl);
358 350
    }
351

  
352
    /* 
353
     * 6.7.3.2 Command Completed Events
354
     *
355
     * Software issues a command to a hot-plug capable Downstream Port by
356
     * issuing a write transaction that targets any portion of the Port’s Slot
357
     * Control register. A single write to the Slot Control register is
358
     * considered to be a single command, even if the write affects more than
359
     * one field in the Slot Control register. In response to this transaction,
360
     * the Port must carry out the requested actions and then set the
361
     * associated status field for the command completed event. */
362

  
363
    /* Real hardware might take a while to complete requested command because
364
     * physical movement would be involved like locking the electromechanical
365
     * lock.  However in our case, command is completed instantaneously above,
366
     * so send a command completion event right now.
367
     */
368
    pcie_cap_slot_event(dev, PCI_EXP_HP_EV_CCI);
359 369
}
360 370

  
361 371
void pcie_cap_slot_push_attention_button(PCIDevice *dev)

Also available in: Unified diff