VirtualBox

Changeset 13189 in vbox for trunk/src/VBox/Devices/Bus


Ignore:
Timestamp:
Oct 11, 2008 12:36:11 PM (16 years ago)
Author:
vboxsync
Message:

PCI: Add support for PCI-to-PCI bridges

Location:
trunk/src/VBox/Devices/Bus
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevPCI.cpp

    r12977 r13189  
    5858#include "../Builtins.h"
    5959
     60/*******************************************************************************
     61*   Structures and Typedefs                                                    *
     62*******************************************************************************/
     63/**
     64 * PIIX3 ISA Bridge state.
     65 */
     66typedef struct PIIX3State
     67{
     68    /** The PCI device of the bridge. */
     69    PCIDEVICE dev;
     70} PIIX3State, PIIX3, *PPIIX3;
     71
     72/**
     73 * PCI Bus instance.
     74 */
     75typedef struct PCIBus
     76{
     77    /** Bus number. */
     78    int32_t             iBus;
     79    /** Start device number. */
     80    int32_t             iDevSearch;
     81
     82#if HC_ARCH_BITS == 64
     83    uint32_t            Alignment0[2];
     84#endif
     85
     86    /** Array of PCI devices. */
     87    R3PTRTYPE(PPCIDEVICE) devices[256];
     88
     89    /** R3 pointer to the device instance. */
     90    PPDMDEVINSR3        pDevInsR3;
     91    /** Pointer to the PCI R3  helpers. */
     92    PCPDMPCIHLPR3       pPciHlpR3;
     93
     94    /** R0 pointer to the device instance. */
     95    PPDMDEVINSR0        pDevInsR0;
     96    /** Pointer to the PCI R0 helpers. */
     97    PCPDMPCIHLPR0       pPciHlpR0;
     98
     99    /** RC pointer to the device instance. */
     100    PPDMDEVINSRC        pDevInsRC;
     101    /** Pointer to the PCI RC helpers. */
     102    PCPDMPCIHLPRC       pPciHlpRC;
     103
     104    /** The PCI device for the PCI bridge. */
     105    PCIDEVICE           PciDev;
     106
     107} PCIBUS;
     108/** Pointer to a PCIBUS instance. */
     109typedef PCIBUS *PPCIBUS;
     110typedef PCIBUS PCIBus;
     111
     112/** @def PCI_IRQ_PINS
     113 * Number of pins for interrupts (PIRQ#0...PIRQ#3)
     114 */
     115#define PCI_IRQ_PINS 4
     116
     117/** @def PCI_APIC_IRQ_PINS
     118 * Number of pins for interrupts if the APIC is used.
     119 */
     120#define PCI_APIC_IRQ_PINS 8
     121
     122/**
     123 * PCI Globals - This is the host-to-pci bridge and the root bus.
     124 */
     125typedef struct PCIGLOBALS
     126{
     127    /** Irq levels for the four PCI Irqs.
     128     *  These count how many devices asserted
     129     *  the IRQ line. If greater 0 an IRQ is sent to the guest.
     130     *  If it drops to 0 the IRQ is deasserted.
     131     */
     132    volatile uint32_t   pci_irq_levels[PCI_IRQ_PINS];
     133
     134#if 1 /* Will be moved into the BIOS soon. */
     135    /** The next I/O port address which the PCI BIOS will use. */
     136    uint32_t            pci_bios_io_addr;
     137    /** The next MMIO address which the PCI BIOS will use. */
     138    uint32_t            pci_bios_mem_addr;
     139    /** Actual bus number. */
     140    uint8_t             uBus;
     141#endif
     142
     143    /** I/O APIC usage flag */
     144    bool                fUseIoApic;
     145    /** I/O APIC irq levels */
     146    volatile uint32_t   pci_apic_irq_levels[PCI_APIC_IRQ_PINS];
     147    /** ACPI IRQ level */
     148    uint32_t            acpi_irq_level;
     149    /** ACPI PIC IRQ */
     150    int                 acpi_irq;
     151    /** Config register. */
     152    uint32_t            uConfigReg;
     153
     154    /** R3 pointer to the device instance. */
     155    PPDMDEVINSR3        pDevInsR3;
     156    /** R0 pointer to the device instance. */
     157    PPDMDEVINSR0        pDevInsR0;
     158    /** RC pointer to the device instance. */
     159    PPDMDEVINSRC        pDevInsRC;
     160
     161#if HC_ARCH_BITS == 64
     162    uint32_t            Alignment0;
     163#endif
     164
     165    /** ISA bridge state. */
     166    PIIX3               PIIX3State;
     167    /** PCI bus which is attached to the host-to-PCI bridge. */
     168    PCIBUS              PciBus;
     169
     170} PCIGLOBALS;
     171/** Pointer to per VM data. */
     172typedef PCIGLOBALS *PPCIGLOBALS;
    60173
    61174/*******************************************************************************
    62175*   Defined Constants And Macros                                               *
    63176*******************************************************************************/
     177
     178/** Converts a bus instance pointer to a device instance pointer. */
     179#define PCIBUS_2_DEVINS(pPciBus)        ((pPciBus)->CTX_SUFF(pDevIns))
     180/** Converts a device instance pointer to a PCIGLOBALS pointer. */
     181#define DEVINS_2_PCIGLOBALS(pDevIns)    ((PPCIGLOBALS)(PDMINS_2_DATA(pDevIns, PPCIGLOBALS)))
     182/** Converts a device instance pointer to a PCIBUS pointer. */
     183#define DEVINS_2_PCIBUS(pDevIns)        ((PPCIBUS)(&PDMINS_2_DATA(pDevIns, PPCIGLOBALS)->PciBus))
     184
     185/** Converts a pointer to a PCI bus instance to a PCIGLOBALS pointer.
     186 *  @note This works only if the bus number is 0!!!
     187 */
     188#define PCIBUS_2_PCIGLOBALS(pPciBus)    ( (PPCIGLOBALS)((uintptr_t)(pPciBus) - RT_OFFSETOF(PCIGLOBALS, PciBus)) )
     189
    64190/** @def PCI_LOCK
    65191 * Acquires the PDM lock. This is a NOP if locking is disabled. */
     
    68194#define PCI_LOCK(pDevIns, rc) \
    69195    do { \
    70         int rc2 = PDMINS_2_DATA(pDevIns, PCIBus *)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \
     196        int rc2 = DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \
    71197        if (rc2 != VINF_SUCCESS) \
    72198            return rc2; \
    73199    } while (0)
    74200#define PCI_UNLOCK(pDevIns) \
    75     PDMINS_2_DATA(pDevIns, PCIBus *)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns)
    76 
    77 
    78 /*******************************************************************************
    79 *   Structures and Typedefs                                                    *
    80 *******************************************************************************/
    81 /**
    82  * PIIX3 ISA Bridge state.
    83  */
    84 typedef struct PIIX3State
    85 {
    86     /** The PCI device of the bridge. */
    87     PCIDEVICE dev;
    88 } PIIX3State, PIIX3, *PPIIX3;
    89 
    90 
    91 /** Maximum number of PCI devices.
    92  * Defined like this to make interrupt handling simple. */
    93 #define PCI_DEVICES_MAX     64
    94 /** Number of uint32_t entries needed make a bitmask of the interrupts. */
    95 #define PCI_IRQ_WORDS       ((PCI_DEVICES_MAX + 31) / 32)
    96 
    97 /**
    98  * PCI Globals.
    99  *
    100  * @remark
    101  * These are currently put in the PCIBus structure since we've
    102  * only got one PCI bus in the current VM configurations. This
    103  * makes life somewhat simpler in RC.
    104  */
    105 typedef struct PCIGLOBALS
    106 {
    107     /** Irq levels for the four PCI Irqs. */
    108     uint32_t            pci_irq_levels[4][PCI_IRQ_WORDS];
    109     /** The base address for PCI assigned MMIO addresses. */
    110     RTGCPHYS32          pci_mem_base;
    111     /** The next I/O port address which the PCI BIOS will use. */
    112     uint32_t            pci_bios_io_addr;
    113     /** The next MMIO address which the PCI BIOS will use. */
    114     uint32_t            pci_bios_mem_addr;
    115     /** I/O APIC usage flag */
    116     bool                fUseIoApic;
    117     /** I/O APIC irq levels */
    118     uint32_t            pci_apic_irq_levels[8][PCI_IRQ_WORDS];
    119     /** ACPI IRQ level */
    120     uint32_t            acpi_irq_level;
    121     /** ACPI PIC IRQ */
    122     int                 acpi_irq;
    123 } PCIGLOBALS;
    124 /** Pointer to per VM data. */
    125 typedef PCIGLOBALS *PPCIGLOBALS;
    126 
    127 
    128 /**
    129  * PCI Bus instance.
    130  */
    131 typedef struct PCIBus
    132 {
    133     /** IRQ index */
    134     uint32_t            uIrqIndex;
    135     /** Bus number. */
    136     int32_t             iBus;
    137     /** Start device number. */
    138     int32_t             iDevSearch;
    139     /** Config register. */
    140     uint32_t            uConfigReg;
    141     /** Array of PCI devices. */
    142     R3PTRTYPE(PPCIDEVICE) devices[256];
    143 
    144     /** R3 pointer to the device instance. */
    145     PPDMDEVINSR3        pDevInsR3;
    146     /** Pointer to the PCI R3  helpers. */
    147     PCPDMPCIHLPR3       pPciHlpR3;
    148 
    149     /** R0 pointer to the device instance. */
    150     PPDMDEVINSR0        pDevInsR0;
    151     /** Pointer to the PCI R0 helpers. */
    152     PCPDMPCIHLPR0       pPciHlpR0;
    153 
    154     /** RC pointer to the device instance. */
    155     PPDMDEVINSRC        pDevInsRC;
    156     /** Pointer to the PCI RC helpers. */
    157     PCPDMPCIHLPRC       pPciHlpRC;
    158 
    159     /** The PCI device for the PCI bridge. */
    160     PCIDEVICE           PciDev;
    161     /** ISA bridge state. */
    162     PIIX3               PIIX3State;
    163     /** The global data.
    164      * Since we've only got one bus at present, we put it here to keep things simple. */
    165     PCIGLOBALS          Globals;
    166 } PCIBUS;
    167 /** Pointer to a PCIBUS instance. */
    168 typedef PCIBUS *PPCIBUS;
    169 typedef PCIBUS PCIBus;
    170 
    171 
    172 /** Converts a bus instance pointer to a device instance pointer. */
    173 #define PCIBUS_2_DEVINS(pPciBus)        ((pPciBus)->CTX_SUFF(pDevIns))
    174 /** Converts a device instance pointer to a PCIGLOBALS pointer. */
    175 #define DEVINS_2_PCIGLOBALS(pDevIns)    ((PPCIGLOBALS)(&PDMINS_2_DATA(pDevIns, PPCIBUS)->Globals))
    176 /** Converts a bus instance pointer to a PCIGLOBALS pointer. */
    177 #define PCIBUS_2_PCIGLOBALS(pPciBus)    ((PPCIGLOBALS)(&pPciBus->Globals))
    178 
     201    DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns)
     202
     203/** @def VBOX_PCI_SAVED_STATE_VERSION
     204 * Saved state version of the PCI bus device.
     205 */
     206#define VBOX_PCI_SAVED_STATE_VERSION 3
    179207
    180208#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    185213
    186214PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
     215PDMBOTHCBDECL(void) pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
    187216
    188217__END_DECLS
    189218
    190 
    191219#define DEBUG_PCI
    192220
    193 #define PCI_VENDOR_ID           0x00    /* 16 bits */
    194 #define PCI_DEVICE_ID           0x02    /* 16 bits */
    195 #define PCI_COMMAND             0x04    /* 16 bits */
    196 #define  PCI_COMMAND_IO         0x1     /* Enable response in I/O space */
    197 #define  PCI_COMMAND_MEMORY     0x2     /* Enable response in Memory space */
    198 #define PCI_CLASS_DEVICE        0x0a    /* Device class */
    199 #define PCI_INTERRUPT_LINE      0x3c    /* 8 bits */
    200 #define PCI_INTERRUPT_PIN       0x3d    /* 8 bits */
    201 #define PCI_MIN_GNT             0x3e    /* 8 bits */
    202 #define PCI_MAX_LAT             0x3f    /* 8 bits */
     221#define PCI_VENDOR_ID       0x00    /* 16 bits */
     222#define PCI_DEVICE_ID       0x02    /* 16 bits */
     223#define PCI_COMMAND         0x04    /* 16 bits */
     224#define  PCI_COMMAND_IO     0x01    /* Enable response in I/O space */
     225#define  PCI_COMMAND_MEMORY 0x02    /* Enable response in Memory space */
     226#define PCI_CLASS_DEVICE    0x0a    /* Device class */
     227#define PCI_INTERRUPT_LINE  0x3c    /* 8 bits */
     228#define PCI_INTERRUPT_PIN   0x3d    /* 8 bits */
     229#define PCI_MIN_GNT         0x3e    /* 8 bits */
     230#define PCI_MAX_LAT         0x3f    /* 8 bits */
    203231
    204232#ifdef IN_RING3
    205233
    206 static void pci_addr_writel(PCIBus *s, uint32_t addr, uint32_t val)
    207 {
    208     s->uConfigReg = val;
    209 }
    210 
    211 static uint32_t pci_addr_readl(PCIBus *s, uint32_t addr)
    212 {
    213     return s->uConfigReg;
     234static void pci_addr_writel(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val)
     235{
     236    pGlobals->uConfigReg = val;
     237}
     238
     239static uint32_t pci_addr_readl(PPCIGLOBALS pGlobals, uint32_t addr)
     240{
     241    return pGlobals->uConfigReg;
    214242}
    215243
    216244static void pci_update_mappings(PCIDevice *d)
    217245{
    218     PPCIBUS pBus = d->Int.s.pBus;
     246    PPCIBUS pBus = d->Int.s.CTX_SUFF(pBus);
    219247    PCIIORegion *r;
    220248    int cmd, i;
     
    282310                        }
    283311                    } else {
    284                         RTGCPHYS GCPhysBase = r->addr + PCIBUS_2_PCIGLOBALS(pBus)->pci_mem_base;
     312                        RTGCPHYS GCPhysBase = r->addr;
    285313                        int rc;
    286314                        if (pBus->pPciHlpR3->pfnIsMMIO2Base(pBus->pDevInsR3, d->pDevIns, GCPhysBase))
     
    299327                if (r->addr != ~0U) {
    300328                    int rc = r->map_func(d, i,
    301                                          r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : PCIBUS_2_PCIGLOBALS(pBus)->pci_mem_base),
     329                                         r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : 0),
    302330                                         r->size, (PCIADDRESSSPACE)(r->type));
    303331                    AssertRC(rc);
     
    411439        }
    412440#ifdef VBOX
    413         /* status register: only clear bits by writing a '1' at the corresponding bit */
     441        /* status register: only clear bits by writing a '1' at the corresponding bit */
    414442        if (addr == 0x06)
    415443        {
     
    437465}
    438466
    439 static void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
     467static void pci_data_write(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
    440468{
    441469    PCIDevice *pci_dev;
    442     int config_addr, iBus;
    443 
    444     Log(("pci_data_write: addr=%08x val=%08x len=%d\n", s->uConfigReg, val, len));
    445 
    446     if (!(s->uConfigReg & (1 << 31))) {
     470    uint8_t iBus, iDevice;
     471    uint32_t config_addr;
     472
     473    Log(("pci_data_write: addr=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
     474
     475    if (!(pGlobals->uConfigReg & (1 << 31))) {
    447476        return;
    448477    }
    449     if ((s->uConfigReg & 0x3) != 0) {
     478    if ((pGlobals->uConfigReg & 0x3) != 0) {
    450479        return;
    451480    }
    452     iBus = (s->uConfigReg >> 16) & 0xff;
     481    iBus = (pGlobals->uConfigReg >> 16) & 0xff;
     482    iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
     483    config_addr = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
    453484    if (iBus != 0)
    454         return;
    455     pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff];
    456     if (!pci_dev)
    457         return;
    458     config_addr = (s->uConfigReg & 0xfc) | (addr & 3);
    459     Log(("pci_config_write: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
    460     pci_dev->Int.s.pfnConfigWrite(pci_dev, config_addr, val, len);
    461 }
    462 
    463 static uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
    464 {
    465     PCIDevice *pci_dev;
    466     int config_addr, iBus;
     485    {
     486        /*
     487         * Search for a fitting bridge. Becuase we don't support multi function devices at the moment
     488         * we only search all devices with function 0 to speed things up.
     489         * If no bridge is found the write will be ignored.
     490         */
     491        for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8)
     492        {
     493            /*
     494             * Examine secondary and subordinate bus number.
     495             * If the target bus is in the range we pass the request on to the bridge.
     496             */
     497            PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev];
     498            if (!pBridgeDevice)
     499                continue;
     500            if (!pBridgeDevice->Int.s.fPciToPciBridge)
     501                continue;
     502
     503            if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
     504                && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
     505            {
     506                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
     507
     508                /* Start the journey... */
     509                pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, val, len);
     510            }
     511        }
     512    }
     513    else
     514    {
     515        pci_dev = pGlobals->PciBus.devices[iDevice];
     516        if (!pci_dev)
     517            return;
     518        Log(("pci_config_write: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
     519        pci_dev->Int.s.pfnConfigWrite(pci_dev, config_addr, val, len);
     520    }
     521}
     522
     523static uint32_t pci_data_read(PPCIGLOBALS pGlobals, uint32_t addr, int len)
     524{
     525    uint8_t iBus, iDevice;
     526    uint32_t config_addr;
    467527    uint32_t val;
    468528
    469     if (!(s->uConfigReg & (1 << 31)))
     529    if (!(pGlobals->uConfigReg & (1 << 31)))
    470530        goto fail;
    471     if ((s->uConfigReg & 0x3) != 0)
     531    if ((pGlobals->uConfigReg & 0x3) != 0)
    472532        goto fail;
    473     iBus = (s->uConfigReg >> 16) & 0xff;
     533    iBus = (pGlobals->uConfigReg >> 16) & 0xff;
     534    iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
     535    config_addr = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
    474536    if (iBus != 0)
    475         goto fail;
    476     pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff];
    477     if (!pci_dev) {
    478     fail:
    479         switch(len) {
    480         case 1:
    481             val = 0xff;
    482             break;
    483         case 2:
    484             val = 0xffff;
    485             break;
    486         default:
    487         case 4:
    488             val = 0xffffffff;
    489             break;
    490         }
    491         goto the_end;
    492     }
    493     config_addr = (s->uConfigReg & 0xfc) | (addr & 3);
    494     val = pci_dev->Int.s.pfnConfigRead(pci_dev, config_addr, len);
    495     Log(("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
     537    {
     538        /*
     539         * Search for a fitting bridge. Becuase we don't support multi function devices at the moment
     540         * we only search all devices with function 0 to speed things up.
     541         * If no bridge is found the read will be ignored.
     542         */
     543        for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8)
     544        {
     545            /*
     546             * Examine secondary and subordinate bus number.
     547             * If the target bus is in the range we pass the request on to the bridge.
     548             */
     549            PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev];
     550            if (!pBridgeDevice)
     551                continue;
     552            if (!pBridgeDevice->Int.s.fPciToPciBridge)
     553                continue;
     554
     555            if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
     556                && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
     557            {
     558                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
     559
     560                val = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, len);
     561            }
     562        }
     563    }
     564    else
     565    {
     566        PCIDevice *pci_dev;
     567
     568        pci_dev = pGlobals->PciBus.devices[iDevice];
     569        if (!pci_dev) {
     570        fail:
     571            switch(len) {
     572            case 1:
     573                val = 0xff;
     574                break;
     575            case 2:
     576                val = 0xffff;
     577                break;
     578            default:
     579            case 4:
     580                val = 0xffffffff;
     581                break;
     582            }
     583            goto the_end;
     584        }
     585        val = pci_dev->Int.s.pfnConfigRead(pci_dev, config_addr, len);
     586        Log(("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
     587    }
     588
    496589 the_end:
    497590    return val;
     
    503596/* return the global irq number corresponding to a given device irq
    504597   pin. We could also use the bus number to have a more precise
    505    mapping. */
    506 static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
     598   mapping.
     599   This is the implementation note described in the PCI spec chapter 2.2.6 */
     600static inline int pci_slot_get_pirq(uint8_t uDevFn, int irq_num)
    507601{
    508602    int slot_addend;
    509     slot_addend = (pci_dev->devfn >> 3) - 1;
     603    slot_addend = (uDevFn >> 3) - 1;
    510604    return (irq_num + slot_addend) & 3;
    511605}
    512606
    513 static inline int pci_slot_get_apic_pirq(PCIDevice *pci_dev, int irq_num)
    514 {
    515     return (irq_num + (pci_dev->devfn >> 3)) & 7;
     607static inline int pci_slot_get_apic_pirq(uint8_t uDevFn, int irq_num)
     608{
     609    return (irq_num + (uDevFn >> 3)) & 7;
    516610}
    517611
    518612static inline int get_pci_irq_apic_level(PPCIGLOBALS pGlobals, int irq_num)
    519613{
    520     int apic_level;
    521     apic_level = ((pGlobals->pci_apic_irq_levels[irq_num][0] |
    522                    pGlobals->pci_apic_irq_levels[irq_num][1]) != 0);
    523     return apic_level;
    524 }
    525 
    526 static void apic_set_irq(PPCIBUS pBus, PCIDevice *pci_dev, int irq_num1, int level, int acpi_irq)
    527 {
     614    return (pGlobals->pci_apic_irq_levels[irq_num] != 0);
     615}
     616
     617static void apic_set_irq(PPCIBUS pBus, uint8_t uDevFn, PCIDevice *pPciDev, int irq_num1, int iLevel, int acpi_irq)
     618{
     619    /* This is only allowed to be called with a pointer to the host bus. */
     620    AssertMsg(pBus->iBus == 0, ("iBus=%u\n", pBus->iBus));
     621
    528622    if (acpi_irq == -1) {
    529         int shift, apic_irq, apic_level;
    530         uint32_t *p;
     623        int apic_irq, apic_level;
    531624        PPCIGLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pBus);
    532         int uIrqIndex = pci_dev->Int.s.iIrq;
    533         int irq_num = pci_slot_get_apic_pirq(pci_dev, irq_num1);
    534 
    535         p = &pGlobals->pci_apic_irq_levels[irq_num][uIrqIndex >> 5];
    536         shift = (uIrqIndex & 0x1f);
    537         *p = (*p & ~(1 << shift)) | ((level & PDM_IRQ_LEVEL_HIGH) << shift);
     625        int irq_num = pci_slot_get_apic_pirq(uDevFn, irq_num1);
     626
     627        if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH)
     628            ASMAtomicIncU32(&pGlobals->pci_apic_irq_levels[irq_num]);
     629        else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW)
     630            ASMAtomicDecU32(&pGlobals->pci_apic_irq_levels[irq_num]);
     631
    538632        apic_irq = irq_num + 0x10;
    539633        apic_level = get_pci_irq_apic_level(pGlobals, irq_num);
    540634        Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d\n",
    541               R3STRING(pci_dev->name), irq_num1, level, apic_irq, apic_level, irq_num));
     635              R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
    542636        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
    543637
    544         if ((level & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) {
    545             *p = (*p & ~(1 << shift));
     638        if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) {
     639            ASMAtomicDecU32(&pGlobals->pci_apic_irq_levels[irq_num]);
     640            pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
    546641            apic_level = get_pci_irq_apic_level(pGlobals, irq_num);
    547642            Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d (flop)\n",
    548                   R3STRING(pci_dev->name), irq_num1, level, apic_irq, apic_level, irq_num));
     643                  R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
    549644            pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
    550645        }
    551646    } else {
    552647        Log3(("apic_set_irq: %s: irq_num1=%d level=%d acpi_irq=%d\n",
    553               R3STRING(pci_dev->name), irq_num1, level, acpi_irq));
    554         pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), acpi_irq, level);
     648              R3STRING(pPciDev->name), irq_num1, iLevel, acpi_irq));
     649        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), acpi_irq, iLevel);
    555650    }
    556651}
     
    558653static inline int get_pci_irq_level(PPCIGLOBALS pGlobals, int irq_num)
    559654{
    560     int pic_level;
    561 #if (PCI_IRQ_WORDS == 2)
    562     pic_level = ((pGlobals->pci_irq_levels[irq_num][0] |
    563                   pGlobals->pci_irq_levels[irq_num][1]) != 0);
    564 #else
    565     {
    566         int i;
     655    return (pGlobals->pci_irq_levels[irq_num] != 0);
     656}
     657
     658/**
     659 * Set the IRQ for a PCI device on the host bus - shared by host bus and bridge.
     660 *
     661 * @param   pDevIns         Device instance of the host PCI Bus.
     662 * @param   uDevFn          The device number on the host bus which will raise the IRQ
     663 * @param   pPciDev         The PCI device structure which raised the interrupt.
     664 * @param   iIrq            IRQ number to set.
     665 * @param   iLevel          IRQ level.
     666 * @remark  uDevFn and pPciDev->devfn are not the same if the device is behind a bridge.
     667 *          In that case uDevFn will be the slot of the bridge which is needed to calculate the
     668 *          PIRQ value.
     669 */
     670static void pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel)
     671{
     672    PPCIBUS     pBus =     &pGlobals->PciBus;
     673    uint8_t    *pbCfg = pGlobals->PIIX3State.dev.config;
     674    const bool  fIsAcpiDevice = pPciDev->config[2] == 0x13 && pPciDev->config[3] == 0x71;
     675    const bool  fIsApicEnabled = pGlobals->fUseIoApic && pbCfg[0xde] == 0xbe && pbCfg[0xad] == 0xef;
     676    int pic_irq, pic_level;
     677
     678    /* Check if the state changed. */
     679    if (pPciDev->Int.s.uIrqPinState != iLevel)
     680    {
     681        pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
     682
     683        /* apic only */
     684        if (fIsApicEnabled)
     685        {
     686            if (fIsAcpiDevice)
     687                /*
     688                 * ACPI needs special treatment since SCI is hardwired and
     689                 * should not be affected by PCI IRQ routing tables at the
     690                 * same time SCI IRQ is shared in PCI sense hence this
     691                 * kludge (i.e. we fetch the hardwired value from ACPIs
     692                 * PCI device configuration space).
     693                 */
     694                apic_set_irq(pBus, uDevFn, pPciDev, -1, iLevel, pPciDev->config[PCI_INTERRUPT_LINE]);
     695            else
     696                apic_set_irq(pBus, uDevFn, pPciDev, iIrq, iLevel, -1);
     697            return;
     698        }
     699
     700        if (fIsAcpiDevice)
     701        {
     702            /* As per above treat ACPI in a special way */
     703            pic_irq = pPciDev->config[PCI_INTERRUPT_LINE];
     704            pGlobals->acpi_irq = pic_irq;
     705            pGlobals->acpi_irq_level = iLevel & PDM_IRQ_LEVEL_HIGH;
     706        }
     707        else
     708        {
     709            int irq_num;
     710            irq_num = pci_slot_get_pirq(uDevFn, iIrq);
     711
     712            if (pPciDev->Int.s.uIrqPinState == PDM_IRQ_LEVEL_HIGH)
     713                ASMAtomicIncU32(&pGlobals->pci_irq_levels[irq_num]);
     714            else if (pPciDev->Int.s.uIrqPinState == PDM_IRQ_LEVEL_LOW)
     715                ASMAtomicDecU32(&pGlobals->pci_irq_levels[irq_num]);
     716
     717            /* now we change the pic irq level according to the piix irq mappings */
     718            pic_irq = pbCfg[0x60 + irq_num];
     719            if (pic_irq >= 16)
     720            {
     721                if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
     722                {
     723                    ASMAtomicDecU32(&pGlobals->pci_irq_levels[irq_num]);
     724                    pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
     725                }
     726
     727                return;
     728            }
     729        }
     730
     731        /* the pic level is the logical OR of all the PCI irqs mapped to it */
    567732        pic_level = 0;
    568         for(i = 0; i < PCI_IRQ_WORDS; i++) {
    569             if (pGlobals->pci_irq_levels[irq_num][i]) {
    570                 pic_level = 1;
    571                 break;
    572             }
    573         }
    574     }
    575 #endif
    576     return pic_level;
    577 }
    578 
    579 /**
    580  * Set the IRQ for a PCI device.
     733        if (pic_irq == pbCfg[0x60])
     734            pic_level |= get_pci_irq_level(pGlobals, 0);
     735        if (pic_irq == pbCfg[0x61])
     736            pic_level |= get_pci_irq_level(pGlobals, 1);
     737        if (pic_irq == pbCfg[0x62])
     738            pic_level |= get_pci_irq_level(pGlobals, 2);
     739        if (pic_irq == pbCfg[0x63])
     740            pic_level |= get_pci_irq_level(pGlobals, 3);
     741        if (pic_irq == pGlobals->acpi_irq)
     742            pic_level |= pGlobals->acpi_irq_level;
     743
     744        Log3(("pciSetIrq: %s: iLevel=%d iIrq=%d pic_irq=%d pic_level=%d\n",
     745              R3STRING(pPciDev->name), iLevel, iIrq, pic_irq, pic_level));
     746        pBus->CTX_SUFF(pPciHlp)->pfnIsaSetIrq(pBus->CTX_SUFF(pDevIns), pic_irq, pic_level);
     747
     748        /** @todo optimize pci irq flip-flop some rainy day. */
     749        if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
     750            pciSetIrqInternal(pGlobals, uDevFn, pPciDev, iIrq, PDM_IRQ_LEVEL_LOW);
     751    }
     752}
     753
     754/**
     755 * Set the IRQ for a PCI device on the host bus.
    581756 *
    582757 * @param   pDevIns         Device instance of the PCI Bus.
     
    587762PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
    588763{
    589     PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
    590     PPCIGLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pBus);
    591     uint8_t    *pbCfg = pBus->PIIX3State.dev.config;
    592     const bool  fIsAcpiDevice = pPciDev->config[2] == 0x13 && pPciDev->config[3] == 0x71;
    593     const bool  fIsApicEnabled = pGlobals->fUseIoApic && pbCfg[0xde] == 0xbe && pbCfg[0xad] == 0xef;
    594     int pic_irq, pic_level;
    595     uint32_t *p;
    596 
    597     /* apic only */
    598     if (fIsApicEnabled)
    599     {
    600         if (fIsAcpiDevice)
    601             /*
    602              * ACPI needs special treatment since SCI is hardwired and
    603              * should not be affected by PCI IRQ routing tables at the
    604              * same time SCI IRQ is shared in PCI sense hence this
    605              * kludge (i.e. we fetch the hardwired value from ACPIs
    606              * PCI device configuration space).
    607              */
    608             apic_set_irq(pBus, pPciDev, -1, iLevel, pPciDev->config[0x3c]);
    609         else
    610             apic_set_irq(pBus, pPciDev, iIrq, iLevel, -1);
    611         return;
    612     }
    613 
    614     if (fIsAcpiDevice)
    615     {
    616         /* As per above treat ACPI in a special way */
    617         pic_irq = pPciDev->config[0x3c];
    618         pGlobals->acpi_irq = pic_irq;
    619         pGlobals->acpi_irq_level = iLevel & PDM_IRQ_LEVEL_HIGH;
    620     }
    621     else
    622     {
    623         int shift, irq_num, uIrqIndex;
    624         irq_num = pci_slot_get_pirq(pPciDev, iIrq);
    625         uIrqIndex = pPciDev->Int.s.iIrq;
    626         p = &pGlobals->pci_irq_levels[irq_num][uIrqIndex >> 5];
    627         shift = (uIrqIndex & 0x1f);
    628         *p = (*p & ~(1 << shift)) | ((iLevel & PDM_IRQ_LEVEL_HIGH) << shift);
    629 
    630         /* now we change the pic irq level according to the piix irq mappings */
    631         pic_irq = pbCfg[0x60 + irq_num];
    632         if (pic_irq >= 16)
    633         {
    634             if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
    635                 *p = (*p & ~(1 << shift));
    636             return;
    637         }
    638     }
    639 
    640     /* the pic level is the logical OR of all the PCI irqs mapped to it */
    641     pic_level = 0;
    642     if (pic_irq == pbCfg[0x60])
    643         pic_level |= get_pci_irq_level(pGlobals, 0);
    644     if (pic_irq == pbCfg[0x61])
    645         pic_level |= get_pci_irq_level(pGlobals, 1);
    646     if (pic_irq == pbCfg[0x62])
    647         pic_level |= get_pci_irq_level(pGlobals, 2);
    648     if (pic_irq == pbCfg[0x63])
    649         pic_level |= get_pci_irq_level(pGlobals, 3);
    650     if (pic_irq == pGlobals->acpi_irq)
    651         pic_level |= pGlobals->acpi_irq_level;
    652 
    653     Log3(("piix3_set_irq: %s: iLevel=%d iIrq=%d pic_irq=%d pic_level=%d\n",
    654           R3STRING(pPciDev->name), iLevel, iIrq, pic_irq, pic_level));
    655     pBus->CTX_SUFF(pPciHlp)->pfnIsaSetIrq(pBus->CTX_SUFF(pDevIns), pic_irq, pic_level);
    656 
    657     /** @todo optimize pci irq flip-flop some rainy day. */
    658     if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
    659         pciSetIrq(pDevIns, pPciDev, iIrq, PDM_IRQ_LEVEL_LOW);
     764    pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), pPciDev->devfn, pPciDev, iIrq, iLevel);
    660765}
    661766
     
    697802}
    698803
    699 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
    700 {
    701     PCIBus *s = d->Int.s.pBus;
    702     s->uConfigReg = 0x80000000 | (s->iBus << 16) |
    703         (d->devfn << 8) | addr;
    704     pci_data_write(s, 0, val, 4);
    705 }
    706 
    707 static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
    708 {
    709     PCIBus *s = d->Int.s.pBus;
    710     s->uConfigReg = 0x80000000 | (s->iBus << 16) |
    711         (d->devfn << 8) | (addr & ~3);
    712     pci_data_write(s, addr & 3, val, 2);
    713 }
    714 
    715 static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
    716 {
    717     PCIBus *s = d->Int.s.pBus;
    718     s->uConfigReg = 0x80000000 | (s->iBus << 16) |
    719         (d->devfn << 8) | (addr & ~3);
    720     pci_data_write(s, addr & 3, val, 1);
    721 }
    722 
    723 static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
    724 {
    725     PCIBus *s = d->Int.s.pBus;
    726     s->uConfigReg = 0x80000000 | (s->iBus << 16) |
    727         (d->devfn << 8) | (addr & ~3);
    728     return pci_data_read(s, addr & 3, 2);
    729 }
    730 
    731 static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
    732 {
    733     PCIBus *s = d->Int.s.pBus;
    734     s->uConfigReg = 0x80000000 | (s->iBus << 16) |
    735         (d->devfn << 8) | (addr & ~3);
    736     return pci_data_read(s, addr & 3, 1);
     804static void pci_config_writel(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val)
     805{
     806    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     807        (uDevFn << 8) | addr;
     808    pci_data_write(pGlobals, 0, val, 4);
     809}
     810
     811static void pci_config_writew(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val)
     812{
     813    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     814        (uDevFn << 8) | (addr & ~3);
     815    pci_data_write(pGlobals, addr & 3, val, 2);
     816}
     817
     818static void pci_config_writeb(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val)
     819{
     820    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     821        (uDevFn << 8) | (addr & ~3);
     822    pci_data_write(pGlobals, addr & 3, val, 1);
     823}
     824
     825static uint32_t pci_config_readl(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr)
     826{
     827    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     828        (uDevFn << 8) | addr;
     829    return pci_data_read(pGlobals, 0, 4);
     830}
     831
     832static uint32_t pci_config_readw(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr)
     833{
     834    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     835        (uDevFn << 8) | (addr & ~3);
     836    return pci_data_read(pGlobals, addr & 3, 2);
     837}
     838
     839static uint32_t pci_config_readb(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr)
     840{
     841    pGlobals->uConfigReg = 0x80000000 | (uBus << 16) |
     842        (uDevFn << 8) | (addr & ~3);
     843    return pci_data_read(pGlobals, addr & 3, 1);
    737844}
    738845
     
    740847static const uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; /* bird: added const */
    741848
    742 static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
    743 {
    744     PCIIORegion *r;
     849static void pci_set_io_region_addr(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, int region_num, uint32_t addr)
     850{
    745851    uint16_t cmd;
    746852    uint32_t ofs;
    747853
    748     if ( region_num == PCI_ROM_SLOT ) {
     854    if ( region_num == PCI_ROM_SLOT )
    749855        ofs = 0x30;
    750     }else{
     856    else
    751857        ofs = 0x10 + region_num * 4;
    752     }
    753 
    754     pci_config_writel(d, ofs, addr);
    755     r = &d->Int.s.aIORegions[region_num];
    756 
    757     /* enable memory mappings */
    758     cmd = pci_config_readw(d, PCI_COMMAND);
     858
     859    /* Read memory type first. */
     860    uint8_t uRessourceType = pci_config_readb(pGlobals, uBus, uDevFn, ofs);
     861    AssertMsg(uRessourceType != 0xff, ("Device non existent\n"));
     862
     863    /* Read command register. */
     864    cmd = pci_config_readw(pGlobals, uBus, uDevFn, PCI_COMMAND);
    759865    if ( region_num == PCI_ROM_SLOT )
    760866        cmd |= 2;
    761     else if (r->type & PCI_ADDRESS_SPACE_IO)
    762         cmd |= 1;
    763     else
    764         cmd |= 2;
    765     pci_config_writew(d, PCI_COMMAND, cmd);
    766 }
    767 
    768 static void pci_bios_init_device(PCIDevice *d)
    769 {
    770     int devclass;
     867    else if ((uRessourceType & 0x01) == 1) /* Test if region is I/O space. */
     868        cmd |= 1; /* Enable I/O space access. */
     869    else /* The region is MMIO. */
     870        cmd |= 2; /* Enable MMIO access. */
     871
     872    /* Write address of the device. */
     873    pci_config_writel(pGlobals, uBus, uDevFn, ofs, addr);
     874
     875    /* enable memory mappings */
     876    pci_config_writew(pGlobals, uBus, uDevFn, PCI_COMMAND, cmd);
     877}
     878
     879static void pci_bios_init_device(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
     880{
    771881    PCIIORegion *r;
    772882    uint32_t *paddr;
    773     int i, pin, pic_irq, vendor_id, device_id;
    774 
    775     devclass = pci_config_readw(d, PCI_CLASS_DEVICE);
    776     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
    777     device_id = pci_config_readw(d, PCI_DEVICE_ID);
    778     switch(devclass)
    779     {
    780     case 0x0101:
    781         if (vendor_id == 0x8086 &&
    782             (device_id == 0x7010 || device_id == 0x7111)) {
    783             /* PIIX3 or PIIX4 IDE */
    784             pci_config_writew(d, 0x40, 0x8000); /* enable IDE0 */
    785             pci_config_writew(d, 0x42, 0x8000); /* enable IDE1 */
    786             goto default_map;
    787         } else {
    788             /* IDE: we map it as in ISA mode */
    789             pci_set_io_region_addr(d, 0, 0x1f0);
    790             pci_set_io_region_addr(d, 1, 0x3f4);
    791             pci_set_io_region_addr(d, 2, 0x170);
    792             pci_set_io_region_addr(d, 3, 0x374);
    793         }
    794         break;
    795     case 0x0300:
    796         if (vendor_id != 0x80ee)
    797             goto default_map;
    798         /* VGA: map frame buffer to default Bochs VBE address */
    799         pci_set_io_region_addr(d, 0, 0xE0000000);
    800         break;
    801     case 0x0800:
    802         /* PIC */
    803         vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
    804         device_id = pci_config_readw(d, PCI_DEVICE_ID);
    805         if (vendor_id == 0x1014) {
    806             /* IBM */
    807             if (device_id == 0x0046 || device_id == 0xFFFF) {
    808                 /* MPIC & MPIC2 */
    809                 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
     883    int i, pin, pic_irq;
     884    uint16_t devclass, vendor_id, device_id;
     885
     886    devclass  = pci_config_readw(pGlobals, uBus, uDevFn, PCI_CLASS_DEVICE);
     887    vendor_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_VENDOR_ID);
     888    device_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_DEVICE_ID);
     889
     890    /* Check if device is present. */
     891    if (vendor_id != 0xffff)
     892    {
     893        switch(devclass)
     894        {
     895            case 0x0101:
     896                if (   (vendor_id == 0x8086)
     897                    && (device_id == 0x7010 || device_id == 0x7111))
     898                {
     899                    /* PIIX3 or PIIX4 IDE */
     900                    pci_config_writew(pGlobals, uBus, uDevFn, 0x40, 0x8000); /* enable IDE0 */
     901                    pci_config_writew(pGlobals, uBus, uDevFn, 0x42, 0x8000); /* enable IDE1 */
     902                    goto default_map;
     903                }
     904                else
     905                {
     906                    /* IDE: we map it as in ISA mode */
     907                    pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x1f0);
     908                    pci_set_io_region_addr(pGlobals, uBus, uDevFn, 1, 0x3f4);
     909                    pci_set_io_region_addr(pGlobals, uBus, uDevFn, 2, 0x170);
     910                    pci_set_io_region_addr(pGlobals, uBus, uDevFn, 3, 0x374);
     911                }
     912                break;
     913            case 0x0300:
     914                if (vendor_id != 0x80ee)
     915                    goto default_map;
     916                /* VGA: map frame buffer to default Bochs VBE address */
     917                pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0xE0000000);
     918                break;
     919            case 0x0800:
     920                /* PIC */
     921                vendor_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_VENDOR_ID);
     922                device_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_DEVICE_ID);
     923                if (vendor_id == 0x1014)
     924                {
     925                    /* IBM */
     926                    if (device_id == 0x0046 || device_id == 0xFFFF)
     927                    {
     928                        /* MPIC & MPIC2 */
     929                        pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x80800000 + 0x00040000);
     930                    }
     931                }
     932                break;
     933            case 0xff00:
     934                if (   (vendor_id == 0x0106b)
     935                    && (device_id == 0x0017 || device_id == 0x0022))
     936                {
     937                    /* macio bridge */
     938                    pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x80800000);
     939                }
     940                break;
     941            case 0x0604:
     942            {
     943                /* Init PCI-to-PCI bridge. */
     944                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_PRIMARY_BUS, uBus);
     945
     946                AssertMsg(pGlobals->uBus < 255, ("Too many bridges on the bus\n"));
     947                pGlobals->uBus++;
     948                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SECONDARY_BUS, pGlobals->uBus);
     949                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, 0xff); /* Temporary until we know how many other bridges are behind this one. */
     950
     951                /* Add position of this bridge into the array. */
     952                paBridgePositions[cBridgeDepth+1] = (uDevFn >> 3);
     953
     954                /*
     955                 * The I/O range for the bridge must be aligned to a 4KB boundary.
     956                 * This does not change anything really as the access to the device is not going
     957                 * through the bridge but we want to be compliant to the spec.
     958                 */
     959                if ((pGlobals->pci_bios_io_addr % 4096) != 0)
     960                    pGlobals->pci_bios_io_addr = RT_ALIGN_32(pGlobals->pci_bios_io_addr, 4*1024);
     961                Log(("%s: Aligned I/O start address. New address %#x\n", __FUNCTION__, pGlobals->pci_bios_io_addr));
     962                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_IO_BASE, (pGlobals->pci_bios_io_addr >> 8) & 0xf0);
     963
     964                /* The MMIO range for the bridge must be aligned to a 1MB boundary. */
     965                if ((pGlobals->pci_bios_mem_addr % (1024 * 1024)) != 0)
     966                    pGlobals->pci_bios_mem_addr = RT_ALIGN_32(pGlobals->pci_bios_mem_addr, 1024*1024);
     967                Log(("%s: Aligned MMIO start address. New address %#x\n", __FUNCTION__, pGlobals->pci_bios_mem_addr));
     968                pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_BASE, (pGlobals->pci_bios_mem_addr >> 16) & UINT32_C(0xffff0));
     969
     970                /* Save values to compare later to. */
     971                uint32_t u32IoAddressBase = pGlobals->pci_bios_io_addr;
     972                uint32_t u32MMIOAddressBase = pGlobals->pci_bios_mem_addr;
     973
     974                /* Init devices behind the bridge and possibly other bridges as well. */
     975                for (int i = 0; i <= 255; i++)
     976                    pci_bios_init_device(pGlobals, uBus + 1, i, cBridgeDepth + 1, paBridgePositions);
     977
     978                /* The number of bridges behind the this one is now available. */
     979                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, pGlobals->uBus);
     980
     981                /*
     982                 * Set I/O limit register. If there is no device with I/O space behind the bridge
     983                 * we set a lower value than in the base register.
     984                 * The result with a real bridge is that no I/O transactions are passed to the secondary
     985                 * interface. Again this doesn't really matter here but we want to be compliant to the spec.
     986                 */
     987                if ((u32IoAddressBase != pGlobals->pci_bios_io_addr) && ((pGlobals->pci_bios_io_addr % 4096) != 0))
     988                {
     989                    /* The upper boundary must be one byte less than a 4KB boundary. */
     990                    pGlobals->pci_bios_io_addr = RT_ALIGN_32(pGlobals->pci_bios_io_addr, 4*1024);
     991                }
     992                pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->pci_bios_io_addr >> 8) & 0xf0) - 1);
     993
     994                /* Same with the MMIO limit register but with 1MB boundary here. */
     995                if ((u32MMIOAddressBase != pGlobals->pci_bios_mem_addr) && ((pGlobals->pci_bios_mem_addr % (1024 * 1024)) != 0))
     996                {
     997                    /* The upper boundary must be one byte less than a 1MB boundary. */
     998                    pGlobals->pci_bios_mem_addr = RT_ALIGN_32(pGlobals->pci_bios_mem_addr, 1024*1024);
     999                }
     1000                pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->pci_bios_mem_addr >> 16) & UINT32_C(0xfff0)) - 1);
     1001
     1002                /*
     1003                 * Set the prefetch base and limit registers. We currently have no device with a prefetchable region
     1004                 * which may be behind a bridge. Thatswhy it is unconditionally disabled here atm by writing a higher value into
     1005                 * the base register than in the limit register.
     1006                 */
     1007                pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_BASE, 0xfff0);
     1008                pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_LIMIT, 0x0);
     1009                pci_config_writel(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, 0x00);
     1010                pci_config_writel(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, 0x00);
     1011                break;
    8101012            }
    811         }
    812         break;
    813     case 0xff00:
    814         if (vendor_id == 0x0106b &&
    815             (device_id == 0x0017 || device_id == 0x0022)) {
    816             /* macio bridge */
    817             pci_set_io_region_addr(d, 0, 0x80800000);
    818         }
    819         break;
    820     default:
    821     default_map:
    822         /* default memory mappings */
    823         for(i = 0; i < PCI_NUM_REGIONS; i++) {
    824             r = &d->Int.s.aIORegions[i];
    825 
    826             if (r->size) {
    827                 if (r->type & PCI_ADDRESS_SPACE_IO)
    828                     paddr = &PCIBUS_2_PCIGLOBALS(d->Int.s.pBus)->pci_bios_io_addr;
    829                 else
    830                     paddr = &PCIBUS_2_PCIGLOBALS(d->Int.s.pBus)->pci_bios_mem_addr;
    831                 *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
    832                 pci_set_io_region_addr(d, i, *paddr);
    833                 *paddr += r->size;
     1013            default:
     1014            default_map:
     1015            {
     1016                /* default memory mappings */
     1017                /*
     1018                 * PCI_NUM_REGIONS is 7 bcause of the rom region but there are only 6 base address register defined by the PCi spec.
     1019                 * Leaving only PCI_NUM_REGIONS would cause reading another and enabling a memory region which does not exist.
     1020                 */
     1021                for(i = 0; i < (PCI_NUM_REGIONS-1); i++)
     1022                {
     1023                    uint32_t u32Size;
     1024                    uint8_t  u8RessourceType;
     1025                    uint32_t u32Address = 0x10 + i * 4;
     1026
     1027                    /* Calculate size. */
     1028                    u8RessourceType = pci_config_readb(pGlobals, uBus, uDevFn, u32Address);
     1029                    pci_config_writel(pGlobals, uBus, uDevFn, u32Address, UINT32_C(0xffffffff));
     1030                    u32Size = pci_config_readl(pGlobals, uBus, uDevFn, u32Address);
     1031                    /* Clear ressource information depending on ressource type. */
     1032                    if ((u8RessourceType & 0x01) == 1) /* I/O */
     1033                        u32Size &= ~(0x01);
     1034                    else                        /* MMIO */
     1035                        u32Size &= ~(0x0f);
     1036
     1037                    /*
     1038                     * Invert all bits and add 1 to get size of the region.
     1039                     * (From PCI implementation note)
     1040                     */
     1041                    if (((u8RessourceType & 0x01) == 1) && (u32Size & UINT32_C(0xffff0000)) == 0)
     1042                        u32Size = (~(u32Size | UINT32_C(0xffff0000))) + 1;
     1043                    else
     1044                        u32Size = (~u32Size) + 1;
     1045
     1046                    Log(("%s: Size of region %u for device %d on bus %d is %u\n", __FUNCTION__, i, uDevFn, uBus, u32Size));
     1047
     1048                    if (u32Size)
     1049                    {
     1050                        if ((u8RessourceType & 0x01) == 1)
     1051                            paddr = &pGlobals->pci_bios_io_addr;
     1052                        else
     1053                            paddr = &pGlobals->pci_bios_mem_addr;
     1054                        *paddr = (*paddr + u32Size - 1) & ~(u32Size - 1);
     1055                        Log(("%s: Start address of %s region %u is %#x\n", __FUNCTION__, ((u8RessourceType & 0x01) == 1 ? "I/O" : "MMIO"), i, *paddr));
     1056                        pci_set_io_region_addr(pGlobals, uBus, uDevFn, i, *paddr);
     1057                        *paddr += u32Size;
     1058                        Log(("%s: New address is %#x\n", __FUNCTION__, *paddr));
     1059                    }
     1060                }
     1061                break;
    8341062            }
    8351063        }
    836         break;
    837     }
    838 
    839     /* map the interrupt */
    840     pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
    841     if (pin != 0) {
    842         pin = pci_slot_get_pirq(d, pin - 1);
    843         pic_irq = pci_irqs[pin];
    844         pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
     1064
     1065        /* map the interrupt */
     1066        pin = pci_config_readb(pGlobals, uBus, uDevFn, PCI_INTERRUPT_PIN);
     1067        if (pin != 0)
     1068        {
     1069            uint8_t uBridgeDevFn = uDevFn;
     1070            pin--;
     1071
     1072            /* We need to go up to the host bus to see which irq this device will assert there. */
     1073            while (cBridgeDepth != 0)
     1074            {
     1075                /* Get the pin the device would assert on the bridge. */
     1076                pin = ((uBridgeDevFn >> 3) + pin) & 3;
     1077                uBridgeDevFn = paBridgePositions[cBridgeDepth];
     1078                cBridgeDepth--;
     1079            }
     1080
     1081            pin = pci_slot_get_pirq(uDevFn, pin);
     1082            pic_irq = pci_irqs[pin];
     1083            pci_config_writeb(pGlobals, uBus, uDevFn, PCI_INTERRUPT_LINE, pic_irq);
     1084        }
    8451085    }
    8461086}
     
    8661106    {
    8671107        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
    868         pci_addr_writel(PDMINS_2_DATA(pDevIns, PCIBus *), Port, u32);
     1108        pci_addr_writel(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32);
    8691109        PCI_UNLOCK(pDevIns);
    8701110    }
     
    8911131    {
    8921132        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
    893         *pu32 = pci_addr_readl(PDMINS_2_DATA(pDevIns, PCIBus *), Port);
     1133        *pu32 = pci_addr_readl(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port);
    8941134        PCI_UNLOCK(pDevIns);
    8951135        Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32));
     
    9211161    {
    9221162        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
    923         pci_data_write(PDMINS_2_DATA(pDevIns, PCIBus *), Port, u32, cb);
     1163        pci_data_write(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32, cb);
    9241164        PCI_UNLOCK(pDevIns);
    9251165    }
     
    9471187    {
    9481188        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
    949         *pu32 = pci_data_read(PDMINS_2_DATA(pDevIns, PCIBus *), Port, cb);
     1189        *pu32 = pci_data_read(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, cb);
    9501190        PCI_UNLOCK(pDevIns);
    9511191        Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x\n", Port, cb, *pu32));
     
    9961236{
    9971237    uint32_t    i;
    998     PPCIBUS     pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
    999     PPCIGLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pThis);
     1238    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     1239    PPCIBUS     pBus =  &pThis->PciBus;
    10001240
    10011241    /*
     
    10031243     */
    10041244    SSMR3PutU32(pSSMHandle, pThis->uConfigReg);
    1005     SSMR3PutBool(pSSMHandle, pGlobals->fUseIoApic);
     1245    SSMR3PutBool(pSSMHandle, pThis->fUseIoApic);
     1246    /*
     1247     * Save IRQ states.
     1248     */
     1249    for (uint8_t i = 0; i < PCI_IRQ_PINS; i++)
     1250        SSMR3PutU32(pSSMHandle, pThis->pci_irq_levels[i]);
     1251    for (uint8_t i = 0; i < PCI_APIC_IRQ_PINS; i++)
     1252        SSMR3PutU32(pSSMHandle, pThis->pci_apic_irq_levels[i]);
     1253
     1254    SSMR3PutU32(pSSMHandle, pThis->acpi_irq_level);
     1255    SSMR3PutS32(pSSMHandle, pThis->acpi_irq);
     1256
    10061257    SSMR3PutU32(pSSMHandle, ~0);        /* separator */
    10071258
     
    10091260     * Iterate all the devices.
    10101261     */
    1011     for (i = 0; i < RT_ELEMENTS(pThis->devices); i++)
    1012     {
    1013         PPCIDEVICE pDev = pThis->devices[i];
     1262    for (i = 0; i < RT_ELEMENTS(pBus->devices); i++)
     1263    {
     1264        PPCIDEVICE pDev = pBus->devices[i];
    10141265        if (pDev)
    10151266        {
     
    10171268            SSMR3PutU32(pSSMHandle, i);
    10181269            SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
    1019             rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.iIrq);
     1270
     1271            rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
    10201272            if (RT_FAILURE(rc))
    10211273                return rc;
     
    10351287static DECLCALLBACK(int) pciLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
    10361288{
    1037     PPCIBUS     pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
    1038     PPCIGLOBALS  pGlobals = PCIBUS_2_PCIGLOBALS(pThis);
     1289    PPCIGLOBALS  pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     1290    PPCIBUS      pBus  = &pThis->PciBus;
    10391291    uint32_t    u32;
    10401292    uint32_t    i;
     
    10441296     * Check the version.
    10451297     */
    1046     if (u32Version > 2)
     1298    if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
    10471299    {
    10481300        AssertFailed();
     
    10551307    SSMR3GetU32(pSSMHandle, &pThis->uConfigReg);
    10561308    if (u32Version > 1)
    1057         SSMR3GetBool(pSSMHandle, &pGlobals->fUseIoApic);
     1309        SSMR3GetBool(pSSMHandle, &pThis->fUseIoApic);
     1310
     1311    /* Load IRQ states. */
     1312    if (u32Version > 2)
     1313    {
     1314        for (uint8_t i = 0; i < PCI_IRQ_PINS; i++)
     1315            SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_irq_levels[i]);
     1316        for (uint8_t i = 0; i < PCI_APIC_IRQ_PINS; i++)
     1317            SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_apic_irq_levels[i]);
     1318
     1319        SSMR3GetU32(pSSMHandle, &pThis->acpi_irq_level);
     1320        SSMR3GetS32(pSSMHandle, &pThis->acpi_irq);
     1321    }
    10581322
    10591323    /* separator */
     
    10781342        if (u32 == (uint32_t)~0)
    10791343            break;
    1080         if (    u32 >= RT_ELEMENTS(pThis->devices)
     1344        if (    u32 >= RT_ELEMENTS(pBus->devices)
    10811345            ||  u32 < i)
    10821346        {
     
    10881352        for (; i < u32; i++)
    10891353        {
    1090             if (pThis->devices[i])
     1354            if (pBus->devices[i])
    10911355            {
    1092                 LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pThis->devices[i]->name,
    1093                         PCIDevGetVendorId(pThis->devices[i]), PCIDevGetDeviceId(pThis->devices[i])));
     1356                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name,
     1357                        PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i])));
    10941358                if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
    10951359                    AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
     
    10971361        }
    10981362
    1099         /* get the data */
     1363        /* Get the data */
     1364        DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
    11001365        SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
    1101         rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.iIrq);
    1102         if (RT_FAILURE(rc))
    1103             return rc;
     1366        if (u32Version < 3)
     1367        {
     1368            int32_t i32Temp;
     1369            /* Irq value not needed anymore. */
     1370            rc = SSMR3GetS32(pSSMHandle, &i32Temp);
     1371            if (RT_FAILURE(rc))
     1372                return rc;
     1373        }
     1374        else
     1375        {
     1376            rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
     1377            if (RT_FAILURE(rc))
     1378                return rc;
     1379        }
    11041380
    11051381        /* check that it's still around. */
    1106         pDev = pThis->devices[i];
     1382        pDev = pBus->devices[i];
    11071383        if (!pDev)
    11081384        {
     
    11251401        /* commit the loaded device config. */
    11261402        memcpy(pDev->config, DevTmp.config, sizeof(pDev->config));
    1127         if (DevTmp.Int.s.iIrq >= PCI_DEVICES_MAX)
    1128         {
    1129             LogRel(("Device %s: Too many devices %d (max=%d)\n", pDev->name, DevTmp.Int.s.iIrq, PCI_DEVICES_MAX));
    1130             AssertFailedReturn(VERR_TOO_MUCH_DATA);
    1131         }
    1132 
    1133         pDev->Int.s.iIrq = DevTmp.Int.s.iIrq;
    1134     }
     1403
     1404        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
     1405    }
     1406
    11351407    return VINF_SUCCESS;
    11361408}
     
    11411413
    11421414/**
    1143  * Registers the device with the default PCI bus.
     1415 * Registers the device with the specified PCI bus.
    11441416 *
    11451417 * @returns VBox status code.
     
    11491421 * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
    11501422 */
    1151 static void pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
    1152 {
    1153     Assert(!pBus->devices[iDev]);
    1154     pPciDev->devfn                  = iDev;
    1155     pPciDev->name                   = pszName;
    1156     pPciDev->Int.s.pBus             = pBus;
    1157     pPciDev->Int.s.pfnConfigRead    = pci_default_read_config;
    1158     pPciDev->Int.s.pfnConfigWrite   = pci_default_write_config;
    1159     AssertMsg(pBus->uIrqIndex < PCI_DEVICES_MAX,
    1160               ("Device %s: Too many devices %d (max=%d)\n",
    1161                pszName, pBus->uIrqIndex, PCI_DEVICES_MAX));
    1162     pPciDev->Int.s.iIrq             = pBus->uIrqIndex++;
    1163     pBus->devices[iDev]             = pPciDev;
    1164     Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
    1165          iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
    1166 }
    1167 
    1168 
    1169 /**
    1170  * Registers the device with the default PCI bus.
    1171  *
    1172  * @returns VBox status code.
    1173  * @param   pDevIns         Device instance of the PCI Bus.
    1174  * @param   pPciDev         The PCI device structure.
    1175  *                          Any PCI enabled device must keep this in it's instance data!
    1176  *                          Fill in the PCI data config before registration, please.
    1177  * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
    1178  * @param   iDev            The PCI device number. Use a negative value for auto assigning one.
    1179  */
    1180 static DECLCALLBACK(int) pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
    1181 {
    1182     PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
    1183 
    1184     /*
    1185      * Check input.
    1186      */
    1187     if (    !pszName
    1188         ||  !pPciDev
    1189         ||  iDev >= (int)RT_ELEMENTS(pBus->devices)
    1190         ||  (iDev >= 0 && iDev <= 8))
    1191     {
    1192         AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
    1193         return VERR_INVALID_PARAMETER;
    1194     }
    1195 
     1423static int pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
     1424{
    11961425    /*
    11971426     * Find device slot.
     
    12401469         * config, do it for all pci devices!
    12411470         */
    1242         AssertReleaseMsg(iDev > 8, ("iDev=%d pszName=%s\n", iDev, pszName));
     1471        //AssertReleaseMsg(iDev > 8 || pBus->iBus != 0, ("iDev=%d pszName=%s\n", iDev, pszName));
    12431472        if (pBus->devices[iDev])
    12441473        {
     
    12931522    }
    12941523
     1524    Assert(!pBus->devices[iDev]);
     1525    pPciDev->devfn                  = iDev;
     1526    pPciDev->name                   = pszName;
     1527    pPciDev->Int.s.pBusR3           = pBus;
     1528    pPciDev->Int.s.pBusR0           = MMHyperR3ToR0(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
     1529    pPciDev->Int.s.pBusRC           = MMHyperR3ToRC(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
     1530    pPciDev->Int.s.pfnConfigRead    = pci_default_read_config;
     1531    pPciDev->Int.s.pfnConfigWrite   = pci_default_write_config;
     1532    pBus->devices[iDev]             = pPciDev;
     1533    Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
     1534         iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
     1535
     1536    return VINF_SUCCESS;
     1537}
     1538
     1539
     1540/**
     1541 * Registers the device with the default PCI bus.
     1542 *
     1543 * @returns VBox status code.
     1544 * @param   pDevIns         Device instance of the PCI Bus.
     1545 * @param   pPciDev         The PCI device structure.
     1546 *                          Any PCI enabled device must keep this in it's instance data!
     1547 *                          Fill in the PCI data config before registration, please.
     1548 * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
     1549 * @param   iDev            The PCI device number. Use a negative value for auto assigning one.
     1550 */
     1551static DECLCALLBACK(int) pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
     1552{
     1553    PPCIBUS     pBus = DEVINS_2_PCIBUS(pDevIns);
     1554
     1555    /*
     1556     * Check input.
     1557     */
     1558    if (    !pszName
     1559        ||  !pPciDev
     1560        ||  iDev >= (int)RT_ELEMENTS(pBus->devices)
     1561        ||  (iDev >= 0 && iDev <= 8))
     1562    {
     1563        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
     1564        return VERR_INVALID_PARAMETER;
     1565    }
     1566
    12951567    /*
    12961568     * Register the device.
    12971569     */
    1298     pciRegisterInternal(pBus, iDev, pPciDev, pszName);
    1299     return VINF_SUCCESS;
     1570    return pciRegisterInternal(pBus, iDev, pPciDev, pszName);
    13001571}
    13011572
     
    13031574static DECLCALLBACK(int) pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
    13041575{
    1305 
    13061576    /*
    13071577     * Validate.
     
    13281598    pRegion->type        = enmType;
    13291599    pRegion->map_func    = pfnCallback;
     1600
     1601    /* Set type in the config space. */
     1602    uint32_t u32Address = 0x10 + iRegion * 4;
     1603    uint32_t u32Value   =   (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH ? (1 << 3) : 0)
     1604                          | (enmType == PCI_ADDRESS_SPACE_IO ? 1 : 0);
     1605    *(uint32_t *)(pPciDev->config + u32Address) = RT_H2LE_U32(u32Value);
     1606
    13301607    return VINF_SUCCESS;
    13311608}
     
    13591636    unsigned    i;
    13601637    uint8_t     elcr[2] = {0, 0};
    1361     PPCIGLOBALS pGlobals = DEVINS_2_PCIGLOBALS(pDevIns);
    1362     PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     1638    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
    13631639    PVM         pVM = PDMDevHlpGetVM(pDevIns);
    13641640    Assert(pVM);
     
    13691645    pGlobals->pci_bios_io_addr  = 0xc000;
    13701646    pGlobals->pci_bios_mem_addr = UINT32_C(0xf0000000);
     1647    pGlobals->uBus = 0;
    13711648
    13721649    /*
     
    13791656        elcr[irq >> 3] |= (1 << (irq & 7));
    13801657        /* Activate irq remapping in PIIX3. */
    1381         pci_config_writeb(&pBus->PIIX3State.dev, 0x60 + i, irq);
     1658        pci_config_writeb(pGlobals, 0, pGlobals->PIIX3State.dev.devfn, 0x60 + i, irq);
    13821659    }
    13831660
     
    13951672     * Init the devices.
    13961673     */
    1397     for (i = 0; i < RT_ELEMENTS(pBus->devices); i++)
     1674    for (i = 0; i < 256; i++)
     1675    {
     1676        uint8_t aBridgePositions[256];
     1677
     1678        memset(aBridgePositions, 0, sizeof(aBridgePositions));
     1679        Log2(("PCI: Initializing device %d (%#x)\n",
     1680              i, 0x80000000 | (i << 8)));
     1681        pci_bios_init_device(pGlobals, 0, i, 0, aBridgePositions);
     1682    }
     1683
     1684    return VINF_SUCCESS;
     1685}
     1686
     1687/**
     1688 * @copydoc FNPDMDEVRELOCATE
     1689 */
     1690static DECLCALLBACK(void) pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     1691{
     1692    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     1693    PPCIBUS     pBus     = &pGlobals->PciBus;
     1694    pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1695
     1696    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
     1697    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1698
     1699    /* Relocate RC pointers for the attached pci devices. */
     1700    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
    13981701    {
    13991702        if (pBus->devices[i])
    1400         {
    1401             Log2(("PCI: Initializing device %d (%#x) '%s'\n",
    1402                   i, 0x80000000 | (i << 8), pBus->devices[i]->name));
    1403             pci_bios_init_device(pBus->devices[i]);
    1404         }
    1405     }
    1406     return VINF_SUCCESS;
    1407 }
    1408 
    1409 /**
    1410  * @copydoc FNPDMDEVRELOCATE
    1411  */
    1412 static DECLCALLBACK(void) pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    1413 {
    1414     PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
    1415     pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    1416     pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
    1417 }
    1418 
    1419 
    1420 /**
    1421  * Construct a PCI Bus device instance for a VM.
     1703            pBus->devices[i]->Int.s.pBusRC += offDelta;
     1704    }
     1705}
     1706
     1707
     1708/**
     1709 * Construct a host to PCI Bus device instance for a VM.
    14221710 *
    14231711 * @returns VBox status.
     
    14671755     * Init data and register the PCI bus.
    14681756     */
    1469     PPCIGLOBALS pGlobals = DEVINS_2_PCIGLOBALS(pDevIns);
    1470     pGlobals->pci_mem_base        = 0;
     1757    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
    14711758    pGlobals->pci_bios_io_addr    = 0xc000;
    14721759    pGlobals->pci_bios_mem_addr   = 0xf0000000;
    1473     memset(&pGlobals->pci_irq_levels, 0, sizeof(pGlobals->pci_irq_levels));
     1760    memset((void *)&pGlobals->pci_irq_levels, 0, sizeof(pGlobals->pci_irq_levels));
    14741761    pGlobals->fUseIoApic          = fUseIoApic;
    1475     memset(&pGlobals->pci_apic_irq_levels, 0, sizeof(pGlobals->pci_apic_irq_levels));
    1476 
    1477     PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
    1478     pBus->pDevInsR3 = pDevIns;
    1479     pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    1480     pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1762    memset((void *)&pGlobals->pci_apic_irq_levels, 0, sizeof(pGlobals->pci_apic_irq_levels));
     1763
     1764    pGlobals->pDevInsR3 = pDevIns;
     1765    pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     1766    pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1767
     1768    pGlobals->PciBus.pDevInsR3 = pDevIns;
     1769    pGlobals->PciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     1770    pGlobals->PciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    14811771
    14821772    PDMPCIBUSREG PciBusReg;
     1773    PPCIBUS      pBus = &pGlobals->PciBus;
    14831774    PciBusReg.u32Version              = PDM_PCIBUSREG_VERSION;
    14841775    PciBusReg.pfnRegisterR3           = pciRegister;
     
    14981789        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
    14991790                                   N_("PCI helper version mismatch; got %#x expected %#x"),
    1500                                    pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION);
     1791                                  pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION);
    15011792
    15021793    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
     
    15191810
    15201811    /* PIIX3 */
    1521     PCIDevSetVendorId(  &pBus->PIIX3State.dev, 0x8086); /* Intel */
    1522     PCIDevSetDeviceId(  &pBus->PIIX3State.dev, 0x7000); /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
    1523     PCIDevSetClassSub(  &pBus->PIIX3State.dev,   0x01); /* PCI_ISA */
    1524     PCIDevSetClassBase( &pBus->PIIX3State.dev,   0x06); /* PCI_bridge */
    1525     PCIDevSetHeaderType(&pBus->PIIX3State.dev,   0x80); /* PCI_multifunction, generic */
    1526 
    1527     pBus->PIIX3State.dev.pDevIns      = pDevIns;
    1528     pBus->PciDev.Int.s.fRequestedDevFn= true;
    1529     pciRegisterInternal(pBus, 8, &pBus->PIIX3State.dev, "PIIX3");
    1530     piix3_reset(&pBus->PIIX3State);
     1812    PCIDevSetVendorId(  &pGlobals->PIIX3State.dev, 0x8086); /* Intel */
     1813    PCIDevSetDeviceId(  &pGlobals->PIIX3State.dev, 0x7000); /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
     1814    PCIDevSetClassSub(  &pGlobals->PIIX3State.dev,   0x01); /* PCI_ISA */
     1815    PCIDevSetClassBase( &pGlobals->PIIX3State.dev,   0x06); /* PCI_bridge */
     1816    PCIDevSetHeaderType(&pGlobals->PIIX3State.dev,   0x80); /* PCI_multifunction, generic */
     1817
     1818    pGlobals->PIIX3State.dev.pDevIns      = pDevIns;
     1819    pGlobals->PIIX3State.dev.Int.s.fRequestedDevFn= true;
     1820    pciRegisterInternal(pBus, 8, &pGlobals->PIIX3State.dev, "PIIX3");
     1821    piix3_reset(&pGlobals->PIIX3State);
    15311822
    15321823    pBus->iDevSearch = 16;
     
    15411832    if (RT_FAILURE(rc))
    15421833        return rc;
    1543     rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, 2, sizeof(*pBus),
     1834    rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus),
    15441835                              NULL, pciSaveExec, NULL, NULL, pciLoadExec, NULL);
    15451836    if (RT_FAILURE(rc))
     
    15721863    1,
    15731864    /* cbInstance */
    1574     sizeof(PCIBUS),
     1865    sizeof(PCIGLOBALS),
    15751866    /* pfnConstruct */
    15761867    pciConstruct,
     
    16061897};
    16071898#endif /* IN_RING3 */
     1899
     1900/**
     1901 * Set the IRQ for a PCI device on a secondary bus.
     1902 *
     1903 * @param   pDevIns         Device instance of the PCI Bus.
     1904 * @param   pPciDev         The PCI device structure.
     1905 * @param   iIrq            IRQ number to set.
     1906 * @param   iLevel          IRQ level.
     1907 */
     1908PDMBOTHCBDECL(void) pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
     1909{
     1910    /*
     1911     * The PCI-to-PCI bridge specification defines how the interrupt pins
     1912     * are routed from the secondary to the primary bus (see chapter 9).
     1913     * iIrq gives the interrupt pin the pci device asserted.
     1914     * We change iIrq here according to the spec and call the SetIrq function
     1915     * of our parent passing the device which asserted the interrupt instead of the device of the bridge.
     1916     */
     1917    PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     1918    int iIrqPinBridge = 0;
     1919    uint8_t uDevFnBridge;
     1920
     1921    /* Walk the chain until we reach the host bus. */
     1922    while (pBus->iBus != 0)
     1923    {
     1924        uDevFnBridge = pBus->PciDev.devfn;
     1925        iIrqPinBridge = ((uDevFnBridge >> 3) + iIrqPinBridge) & 3;
     1926        /* Get the parent. */
     1927        pBus = pBus->PciDev.Int.s.CTX_SUFF(pBus);
     1928    }
     1929
     1930    AssertMsg(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus));
     1931    pciSetIrqInternal(PCIBUS_2_PCIGLOBALS(pBus), uDevFnBridge, pPciDev, iIrqPinBridge, iLevel);
     1932}
     1933
     1934#ifdef IN_RING3
     1935
     1936static void pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb)
     1937{
     1938    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     1939
     1940    LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, u32Value, cb));
     1941
     1942    /* If the current bus is not the target bus search for the bus which contains the device. */
     1943    if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS])
     1944    {
     1945        /*
     1946         * Search for a fitting bridge. Becuase we don't support multi function devices at the moment
     1947         * we only search all devices with function 0 to speed things up.
     1948         * If no bridge is found the write will be ignored.
     1949         */
     1950        for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8)
     1951        {
     1952            /*
     1953             * Examine secondary and subordinate bus number.
     1954             * If the target bus is in the range we pass the request on to the bridge.
     1955             */
     1956            PPCIDEVICE pBridgeDevice = pBus->devices[iDev];
     1957            if (!pBridgeDevice)
     1958                continue;
     1959            if (!pBridgeDevice->Int.s.fPciToPciBridge)
     1960                continue;
     1961
     1962            if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
     1963                && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
     1964            {
     1965                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
     1966
     1967                pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb);
     1968            }
     1969        }
     1970    }
     1971    else
     1972    {
     1973        /* This is the target bus, pass the write to the device. */
     1974        PPCIDEVICE pPciDev = pBus->devices[iDevice];
     1975        if (pPciDev)
     1976        {
     1977            Log(("%s: %s: addr=%02x val=%08x len=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb));
     1978            pPciDev->Int.s.pfnConfigWrite(pPciDev, u32Address, u32Value, cb);
     1979        }
     1980    }
     1981}
     1982
     1983static uint32_t pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb)
     1984{
     1985    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     1986    uint32_t u32Value = 0xffffffff; /* Return value in case there is no device. */
     1987
     1988    LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, cb));
     1989
     1990    /* If the current bus is not the target bus search for the bus which contains the device. */
     1991    if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS])
     1992    {
     1993        /*
     1994         * Search for a fitting bridge. Because we don't support multi function devices at the moment
     1995         * we only search all devices with function 0 to speed things up.
     1996         * If no bridge is found the read will return 0xffffffff.
     1997         */
     1998        for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8)
     1999        {
     2000            /*
     2001             * Examine secondary and subordinate bus number.
     2002             * If the target bus is in the range we pass the request on to the bridge.
     2003             */
     2004            PPCIDEVICE pBridgeDevice = pBus->devices[iDev];
     2005            if (!pBridgeDevice)
     2006                continue;
     2007            if (!pBridgeDevice->Int.s.fPciToPciBridge)
     2008                continue;
     2009
     2010            if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
     2011                && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
     2012            {
     2013                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
     2014
     2015                u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb);
     2016            }
     2017        }
     2018    }
     2019    else
     2020    {
     2021        /* This is the target bus, pass the read to the device. */
     2022        PPCIDEVICE pPciDev = pBus->devices[iDevice];
     2023        if (pPciDev)
     2024        {
     2025            u32Value = pPciDev->Int.s.pfnConfigRead(pPciDev, u32Address, cb);
     2026            Log(("%s: %s: u32Address=%02x u32Value=%08x cb=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb));
     2027        }
     2028    }
     2029
     2030    return u32Value;
     2031}
     2032
     2033/**
     2034 * Saves a state of a PCI bridge device.
     2035 *
     2036 * @returns VBox status code.
     2037 * @param   pDevIns     The device instance.
     2038 * @param   pPciDev     Pointer to PCI device.
     2039 * @param   pSSMHandle  The handle to save the state to.
     2040 */
     2041static DECLCALLBACK(int) pcibridgeSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
     2042{
     2043    uint32_t    i;
     2044    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2045
     2046    /*
     2047     * Iterate all the devices.
     2048     */
     2049    for (i = 0; i < RT_ELEMENTS(pThis->devices); i++)
     2050    {
     2051        PPCIDEVICE pDev = pThis->devices[i];
     2052        if (pDev)
     2053        {
     2054            int rc;
     2055            SSMR3PutU32(pSSMHandle, i);
     2056            SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
     2057
     2058            rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState);
     2059            if (RT_FAILURE(rc))
     2060                return rc;
     2061        }
     2062    }
     2063    return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
     2064}
     2065
     2066/**
     2067 * Loads a saved PCI bridge device state.
     2068 *
     2069 * @returns VBox status code.
     2070 * @param   pDevIns     The device instance.
     2071 * @param   pSSMHandle  The handle to the saved state.
     2072 * @param   u32Version  The data unit version number.
     2073 */
     2074static DECLCALLBACK(int) pcibridgeLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
     2075{
     2076    PPCIBUS      pBus  = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2077    uint32_t    u32;
     2078    uint32_t    i;
     2079    int         rc;
     2080
     2081    /*
     2082     * Check the version.
     2083     */
     2084    if (u32Version > VBOX_PCI_SAVED_STATE_VERSION)
     2085    {
     2086        AssertFailed();
     2087        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
     2088    }
     2089
     2090    /*
     2091     * Iterate all the devices.
     2092     */
     2093    for (i = 0;; i++)
     2094    {
     2095        PCIDEVICE   DevTmp;
     2096        PPCIDEVICE  pDev;
     2097
     2098        /* index / terminator */
     2099        rc = SSMR3GetU32(pSSMHandle, &u32);
     2100        if (RT_FAILURE(rc))
     2101            return rc;
     2102        if (u32 == (uint32_t)~0)
     2103            break;
     2104        if (    u32 >= RT_ELEMENTS(pBus->devices)
     2105            ||  u32 < i)
     2106        {
     2107            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
     2108            return rc;
     2109        }
     2110
     2111        /* skip forward to the device checking that no new devices are present. */
     2112        for (; i < u32; i++)
     2113        {
     2114            if (pBus->devices[i])
     2115            {
     2116                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name,
     2117                        PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i])));
     2118                if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
     2119                    AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
     2120            }
     2121        }
     2122
     2123        /* get the data */
     2124        DevTmp.Int.s.uIrqPinState = 0;
     2125        SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
     2126        rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState);
     2127        if (RT_FAILURE(rc))
     2128            return rc;
     2129
     2130        /* check that it's still around. */
     2131        pDev = pBus->devices[i];
     2132        if (!pDev)
     2133        {
     2134            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
     2135                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
     2136            if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT)
     2137                AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
     2138            continue;
     2139        }
     2140
     2141        /* match the vendor id assuming that this will never be changed. */
     2142        if (    DevTmp.config[0] != pDev->config[0]
     2143            ||  DevTmp.config[1] != pDev->config[1])
     2144        {
     2145            LogRel(("Device in slot %#x (%s) vendor id mismatch! saved=%.4Vhxs current=%.4Vhxs\n",
     2146                    i, pDev->name, DevTmp.config, pDev->config));
     2147            AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
     2148        }
     2149
     2150        /* commit the loaded device config. */
     2151        memcpy(pDev->config, DevTmp.config, sizeof(pDev->config));
     2152
     2153        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
     2154    }
     2155
     2156    return VINF_SUCCESS;
     2157}
     2158
     2159/**
     2160 * @copydoc FNPDMDEVRESET
     2161 */
     2162static DECLCALLBACK(void) pcibridgeReset(PPDMDEVINS pDevIns)
     2163{
     2164    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2165
     2166    /* Reset config space to default values. */
     2167    pBus->PciDev.config[VBOX_PCI_PRIMARY_BUS] = 0;
     2168    pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS] = 0;
     2169    pBus->PciDev.config[VBOX_PCI_SUBORDINATE_BUS] = 0;
     2170}
     2171
     2172/**
     2173 * @copydoc FNPDMDEVRELOCATE
     2174 */
     2175static DECLCALLBACK(void) pcibridgeRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     2176{
     2177    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2178    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     2179
     2180    /* Relocate RC pointers for the attached pci devices. */
     2181    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
     2182    {
     2183        if (pBus->devices[i])
     2184            pBus->devices[i]->Int.s.pBusRC += offDelta;
     2185    }
     2186}
     2187
     2188/**
     2189 * Registers the device with the default PCI bus.
     2190 *
     2191 * @returns VBox status code.
     2192 * @param   pDevIns         Device instance of the PCI Bus.
     2193 * @param   pPciDev         The PCI device structure.
     2194 *                          Any PCI enabled device must keep this in it's instance data!
     2195 *                          Fill in the PCI data config before registration, please.
     2196 * @param   pszName         Pointer to device name (permanent, readonly). For debugging, not unique.
     2197 * @param   iDev            The PCI device number. Use a negative value for auto assigning one.
     2198 */
     2199static DECLCALLBACK(int) pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
     2200{
     2201    PPCIBUS     pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2202
     2203    /*
     2204     * Check input.
     2205     */
     2206    if (    !pszName
     2207        ||  !pPciDev
     2208        ||  iDev >= (int)RT_ELEMENTS(pBus->devices))
     2209    {
     2210        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
     2211        return VERR_INVALID_PARAMETER;
     2212    }
     2213
     2214    /*
     2215     * Register the device.
     2216     */
     2217    return pciRegisterInternal(pBus, iDev, pPciDev, pszName);
     2218}
     2219
     2220/**
     2221 * Construct a PCI bridge device instance for a VM.
     2222 *
     2223 * @returns VBox status.
     2224 * @param   pDevIns     The device instance data.
     2225 *                      If the registration structure is needed, pDevIns->pDevReg points to it.
     2226 * @param   iInstance   Instance number. Use this to figure out which registers and such to use.
     2227 *                      The device number is also found in pDevIns->iInstance, but since it's
     2228 *                      likely to be freqently used PDM passes it as parameter.
     2229 * @param   pCfgHandle  Configuration node handle for the device. Use this to obtain the configuration
     2230 *                      of the device instance. It's also found in pDevIns->pCfgHandle, but like
     2231 *                      iInstance it's expected to be used a bit in this function.
     2232 */
     2233static DECLCALLBACK(int)   pcibridgeConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
     2234{
     2235    int rc;
     2236
     2237    /*
     2238     * Validate and read configuration.
     2239     */
     2240    if (!CFGMR3AreValuesValid(pCfgHandle, "GCEnabled\0" "R0Enabled\0"))
     2241        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
     2242
     2243    /* check if RC code is enabled. */
     2244    bool fGCEnabled;
     2245    rc = CFGMR3QueryBoolDef(pCfgHandle, "GCEnabled", &fGCEnabled, true);
     2246    if (RT_FAILURE(rc))
     2247        return PDMDEV_SET_ERROR(pDevIns, rc,
     2248                                N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
     2249
     2250    /* check if R0 code is enabled. */
     2251    bool fR0Enabled;
     2252    rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &fR0Enabled, true);
     2253    if (RT_FAILURE(rc))
     2254        return PDMDEV_SET_ERROR(pDevIns, rc,
     2255                                N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
     2256    Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
     2257
     2258    /*
     2259     * Init data and register the PCI bus.
     2260     */
     2261    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
     2262    pBus->pDevInsR3 = pDevIns;
     2263    pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     2264    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     2265
     2266    PDMPCIBUSREG PciBusReg;
     2267    PciBusReg.u32Version              = PDM_PCIBUSREG_VERSION;
     2268    PciBusReg.pfnRegisterR3           = pcibridgeRegister;
     2269    PciBusReg.pfnIORegionRegisterR3   = pciIORegionRegister;
     2270    PciBusReg.pfnSetConfigCallbacksR3 = pciSetConfigCallbacks;
     2271    PciBusReg.pfnSetIrqR3             = pcibridgeSetIrq;
     2272    PciBusReg.pfnSaveExecR3           = pciGenericSaveExec;
     2273    PciBusReg.pfnLoadExecR3           = pciGenericLoadExec;
     2274    PciBusReg.pfnFakePCIBIOSR3        = NULL; /* Only needed for the first bus. */
     2275    PciBusReg.pszSetIrqRC             = fGCEnabled ? "pcibridgeSetIrq" : NULL;
     2276    PciBusReg.pszSetIrqR0             = fR0Enabled ? "pcibridgeSetIrq" : NULL;
     2277    rc = pDevIns->pDevHlpR3->pfnPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
     2278    if (RT_FAILURE(rc))
     2279        return PDMDEV_SET_ERROR(pDevIns, rc,
     2280                                N_("Failed to register ourselves as a PCI Bus"));
     2281    if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
     2282        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
     2283                                   N_("PCI helper version mismatch; got %#x expected %#x"),
     2284                                   pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
     2285
     2286    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
     2287    pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
     2288
     2289    /*
     2290     * Fill in PCI configs and add them to the bus.
     2291     */
     2292    PCIDevSetVendorId(  &pBus->PciDev, 0x8086); /* Intel */
     2293    PCIDevSetDeviceId(  &pBus->PciDev, 0x2448); /* 82801 Mobile PCI bridge. */
     2294    PCIDevSetRevisionId(&pBus->PciDev,   0xf2);
     2295    PCIDevSetClassSub(  &pBus->PciDev,   0x04); /* pci2pci */
     2296    PCIDevSetClassBase( &pBus->PciDev,   0x06); /* PCI_bridge */
     2297    PCIDevSetClassProg( &pBus->PciDev,   0x01); /* Supports subtractive decoding. */
     2298    PCIDevSetHeaderType(&pBus->PciDev,   0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
     2299    PCIDevSetCommand(   &pBus->PciDev,   0x00);
     2300    PCIDevSetStatus(    &pBus->PciDev,   0x20); /* 66MHz Capable. */
     2301    PCIDevSetInterruptLine(&pBus->PciDev, 0x00); /* This device does not assert interrupts. */
     2302
     2303    /*
     2304     * This device does not generate interrupts. Interrupt delivery from
     2305     * devices attached to the bus is unaffected.
     2306     */
     2307    PCIDevSetInterruptPin (&pBus->PciDev, 0x00);
     2308
     2309    pBus->PciDev.pDevIns                    = pDevIns;
     2310    pBus->PciDev.Int.s.fPciToPciBridge      = true;
     2311    pBus->PciDev.Int.s.pfnBridgeConfigRead  = pcibridgeConfigRead;
     2312    pBus->PciDev.Int.s.pfnBridgeConfigWrite = pcibridgeConfigWrite;
     2313
     2314    /*
     2315     * Register this PCI bridge. The called function will take care on which bus we will get registered.
     2316     */
     2317    rc = PDMDevHlpPCIRegister (pDevIns, &pBus->PciDev);
     2318    if (RT_FAILURE(rc))
     2319        return rc;
     2320
     2321    pBus->iDevSearch = 0;
     2322    /*
     2323     * The iBus property doesn't really represent the bus number
     2324     * because the guest and the BIOS can choose different bus numbers
     2325     * for them.
     2326     * The bus number is mainly for the setIrq function to indicate
     2327     * when the host bus is reached which will have iBus = 0.
     2328     * Thathswhy the + 1.
     2329     */
     2330    pBus->iBus = iInstance + 1;
     2331
     2332    /*
     2333     * Register SSM handlers. We use the same saved state version as for the host bridge
     2334     * to make changes easier.
     2335     */
     2336    rc = PDMDevHlpSSMRegister(pDevIns, "pcibridge", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus),
     2337                              NULL, pcibridgeSaveExec, NULL, NULL, pcibridgeLoadExec, NULL);
     2338    if (RT_FAILURE(rc))
     2339        return rc;
     2340
     2341    return VINF_SUCCESS;
     2342}
     2343
     2344/**
     2345 * The device registration structure
     2346 * for the PCI-to-PCI bridge.
     2347 */
     2348const PDMDEVREG g_DevicePCIBridge =
     2349{
     2350    /* u32Version */
     2351    PDM_DEVREG_VERSION,
     2352    /* szDeviceName */
     2353    "pcibridge",
     2354    /* szGCMod */
     2355    "VBoxDDGC.gc",
     2356    /* szR0Mod */
     2357    "VBoxDDR0.r0",
     2358    /* pszDescription */
     2359    "82801 Mobile PCI to PCI bridge",
     2360    /* fFlags */
     2361    PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
     2362    /* fClass */
     2363    PDM_DEVREG_CLASS_BUS_PCI,
     2364    /* cMaxInstances */
     2365    ~0,
     2366    /* cbInstance */
     2367    sizeof(PCIBUS),
     2368    /* pfnConstruct */
     2369    pcibridgeConstruct,
     2370    /* pfnDestruct */
     2371    NULL,
     2372    /* pfnRelocate */
     2373    pcibridgeRelocate,
     2374    /* pfnIOCtl */
     2375    NULL,
     2376    /* pfnPowerOn */
     2377    NULL,
     2378    /* pfnReset */
     2379    pcibridgeReset,
     2380    /* pfnSuspend */
     2381    NULL,
     2382    /* pfnResume */
     2383    NULL,
     2384    /* pfnAttach */
     2385    NULL,
     2386    /* pfnDetach */
     2387    NULL,
     2388    /* pfnQueryInterface */
     2389    NULL,
     2390    /* pfnInitComplete */
     2391    NULL,
     2392    /* pfnPowerOff */
     2393    NULL,
     2394    /* pfnSoftReset */
     2395    NULL,
     2396    /* u32VersionEnd */
     2397    PDM_DEVREG_VERSION
     2398};
     2399
     2400#endif /* IN_RING3 */
    16082401#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
  • trunk/src/VBox/Devices/Bus/PCIInternal.h

    r11230 r13189  
    4141
    4242/**
     43 * Callback function for reading from the PCI configuration space.
     44 *
     45 * @returns The register value.
     46 * @param   pDevIns         Pointer to the device instance of the PCI bus.
     47 * @param   iBus            The bus number this device is on.
     48 * @param   iDevice         The number of the device on the bus.
     49 * @param   Address         The configuration space register address. [0..255]
     50 * @param   cb              The register size. [1,2,4]
     51 */
     52typedef DECLCALLBACK(uint32_t) FNPCIBRIDGECONFIGREAD(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb);
     53/** Pointer to a FNPCICONFIGREAD() function. */
     54typedef FNPCIBRIDGECONFIGREAD *PFNPCIBRIDGECONFIGREAD;
     55/** Pointer to a PFNPCICONFIGREAD. */
     56typedef PFNPCIBRIDGECONFIGREAD *PPFNPCIBRIDGECONFIGREAD;
     57
     58/**
     59 * Callback function for writing to the PCI configuration space.
     60 *
     61 * @param   pDevIns         Pointer to the device instance of the PCI bus.
     62 * @param   iBus            The bus number this device is on.
     63 * @param   iDevice         The number of the device on the bus.
     64 * @param   Address         The configuration space register address. [0..255]
     65 * @param   u32Value        The value that's being written. The number of bits actually used from
     66 *                          this value is determined by the cb parameter.
     67 * @param   cb              The register size. [1,2,4]
     68 */
     69typedef DECLCALLBACK(void) FNPCIBRIDGECONFIGWRITE(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb);
     70/** Pointer to a FNPCICONFIGWRITE() function. */
     71typedef FNPCIBRIDGECONFIGWRITE *PFNPCIBRIDGECONFIGWRITE;
     72/** Pointer to a PFNPCICONFIGWRITE. */
     73typedef PFNPCIBRIDGECONFIGWRITE *PPFNPCIBRIDGECONFIGWRITE;
     74
     75/**
    4376 * PCI Device - Internal data.
    4477 */
     
    4780    /** I/O regions. */
    4881    PCIIOREGION                     aIORegions[PCI_NUM_REGIONS];
    49     /** Pointer to the PCI bus of the device. */
    50     R3PTRTYPE(struct PCIBus *)      pBus;
     82    /** Pointer to the PCI bus of the device. - R3 ptr */
     83    R3PTRTYPE(struct PCIBus *)      pBusR3;
     84    /** Pointer to the PCI bus of the device. - R0 ptr */
     85    R0PTRTYPE(struct PCIBus *)      pBusR0;
     86    /** Pointer to the PCI bus of the device. - RC ptr */
     87    RCPTRTYPE(struct PCIBus *)      pBusRC;
     88
     89#if HC_ARCH_BITS == 64
     90    uint32_t                        Alignment0;
     91#endif
     92
    5193    /** Read config callback. */
    5294    R3PTRTYPE(PFNPCICONFIGREAD)     pfnConfigRead;
    5395    /** Write config callback. */
    5496    R3PTRTYPE(PFNPCICONFIGWRITE)    pfnConfigWrite;
    55     /** The irq assigned to the device. */
    56     int32_t                         iIrq;
     97
     98#if HC_ARCH_BITS == 64
     99    uint32_t                        Alignment1;
     100#endif
     101
    57102    /** Set if the specific device fun was requested by PDM.
    58103     * If clear the device and it's functions can be relocated to satisfy the slot request of another device. */
    59104    bool                            fRequestedDevFn;
     105    /** Flag whether the device is a pci-to-pci bridge. */
     106    bool                            fPciToPciBridge;
     107    /** Current state of the IRQ pin of the device. */
     108    int32_t                         uIrqPinState;
     109
     110#if HC_ARCH_BITS == 64
     111    uint32_t                        Alignment2;
     112#endif
     113
     114    /** Read config callback for PCI bridges to pass requests
     115     *  to devices on another bus.
     116     */
     117    R3PTRTYPE(PFNPCIBRIDGECONFIGREAD) pfnBridgeConfigRead;
     118    /** Write config callback for PCI bridges to pass requests
     119     *  to devices on another bus.
     120     */
     121    R3PTRTYPE(PFNPCIBRIDGECONFIGWRITE) pfnBridgeConfigWrite;
     122
    60123} PCIDEVICEINT;
    61124
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette