VirtualBox

Changeset 32263 in vbox


Ignore:
Timestamp:
Sep 7, 2010 6:58:20 AM (14 years ago)
Author:
vboxsync
Message:

PCI work: registers, irqs, part of autoconfig

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pci.h

    r30898 r32263  
    359359}
    360360
     361/**
     362 * Gets the header type config register.
     363 *
     364 * @param   pPciDev         The PCI device.
     365 * @returns u8HdrType       The header type.
     366 */
     367DECLINLINE(uint8_t) PCIDevGetHeaderType(PPCIDEVICE pPciDev)
     368{
     369    return pPciDev->config[VBOX_PCI_HEADER_TYPE];
     370}
     371
    361372
    362373/**
     
    470481{
    471482    return pPciDev->config[VBOX_PCI_CAPABILITY_LIST];
    472 } 
     483}
    473484
    474485/**
  • trunk/src/VBox/Devices/Bus/DevPciIch9.cpp

    r32216 r32263  
    4141
    4242    /** Array of PCI devices. We assume 32 slots, each with 8 functions. */
    43     R3PTRTYPE(PPCIDEVICE) devices[256];
     43    R3PTRTYPE(PPCIDEVICE)   apDevices[256];
    4444    /** Array of bridges attached to the bus. */
    4545    R3PTRTYPE(PPCIDEVICE *) papBridgesR3;
     
    6161
    6262    /** The PCI device for the PCI bridge. */
    63     PCIDEVICE           PciDev;
     63    PCIDEVICE           aPciDev;
    6464
    6565} PCIBUS, *PPCIBUS;
     
    9292#endif
    9393
    94     /** PIC irq levels */
    95     volatile uint32_t   uaPicPciIrqLevels[PCI_IRQ_PINS];
    9694    /** I/O APIC irq levels */
    9795    volatile uint32_t   uaPciApicIrqLevels[PCI_APIC_IRQ_PINS];
    9896
    99     /** ACPI IRQ level */
    100     uint32_t            uAcpiIrqLevel;
    101     /** .. and number */
    102     uint32_t            uAcpiIrq;
     97#if 1 /* Will be moved into the BIOS soon. */
     98    /** The next I/O port address which the PCI BIOS will use. */
     99    uint32_t            uPciBiosIo;
     100    /** The next MMIO address which the PCI BIOS will use. */
     101    uint32_t            uPciBiosMmio;
     102    /** Actual bus number. */
     103    uint8_t             uBus;
     104#endif
     105
    103106
    104107    /** Config register. */
    105108    uint32_t            uConfigReg;
    106 
    107     /** I/O APIC usage flag */
    108     bool                fUseIoApic;
    109 
    110109
    111110    /** PCI bus which is attached to the host-to-PCI bridge. */
     
    130129/** Converts a device instance pointer to a PCIBUS pointer. */
    131130#define DEVINS_2_PCIBUS(pDevIns)        ((PPCIBUS)(&PDMINS_2_DATA(pDevIns, PPCIGLOBALS)->aPciBus))
     131/** Converts a pointer to a PCI root bus instance to a PCIGLOBALS pointer.
     132 */
     133#define PCIROOTBUS_2_PCIGLOBALS(pPciBus)    ( (PPCIGLOBALS)((uintptr_t)(pPciBus) - RT_OFFSETOF(PCIGLOBALS, aPciBus)) )
     134
     135
     136/** @def PCI_LOCK
     137 * Acquires the PDM lock. This is a NOP if locking is disabled. */
     138/** @def PCI_UNLOCK
     139 * Releases the PDM lock. This is a NOP if locking is disabled. */
     140#define PCI_LOCK(pDevIns, rc) \
     141    do { \
     142        int rc2 = DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \
     143        if (rc2 != VINF_SUCCESS) \
     144            return rc2; \
     145    } while (0)
     146#define PCI_UNLOCK(pDevIns) \
     147    DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns)
    132148
    133149#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    142158PDMBOTHCBDECL(int)  ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
    143159
     160RT_C_DECLS_END
     161
     162/* Prototypes */
     163static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel);
    144164#ifdef IN_RING3
     165static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName);
     166static void ich9pciUpdateMappings(PCIDevice *d);
     167static DECLCALLBACK(uint32_t) ich9pciConfigRead(PCIDevice *aDev, uint32_t u32Address, unsigned len);
    145168DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus);
    146169#endif
    147170
    148 RT_C_DECLS_END
    149 
    150 
    151171PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
    152172{
    153     return;
     173    ich9pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), pPciDev->devfn, pPciDev, iIrq, iLevel);
    154174}
    155175
    156176PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
    157177{
    158     return;
    159 }
    160 
     178    /*
     179     * The PCI-to-PCI bridge specification defines how the interrupt pins
     180     * are routed from the secondary to the primary bus (see chapter 9).
     181     * iIrq gives the interrupt pin the pci device asserted.
     182     * We change iIrq here according to the spec and call the SetIrq function
     183     * of our parent passing the device which asserted the interrupt instead of the device of the bridge.
     184     */
     185    PPCIBUS    pBus          = PDMINS_2_DATA(pDevIns, PPCIBUS);
     186    PPCIDEVICE pPciDevBus    = pPciDev;
     187    int        iIrqPinBridge = iIrq;
     188    uint8_t    uDevFnBridge  = 0;
     189
     190    /* Walk the chain until we reach the host bus. */
     191    do
     192    {
     193        uDevFnBridge  = pBus->aPciDev.devfn;
     194        iIrqPinBridge = ((pPciDevBus->devfn >> 3) + iIrqPinBridge) & 3;
     195
     196        /* Get the parent. */
     197        pBus = pBus->aPciDev.Int.s.CTX_SUFF(pBus);
     198        pPciDevBus = &pBus->aPciDev;
     199    } while (pBus->iBus != 0);
     200
     201    AssertMsgReturnVoid(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus));
     202    ich9pciSetIrqInternal(PCIROOTBUS_2_PCIGLOBALS(pBus), uDevFnBridge, pPciDev, iIrqPinBridge, iLevel);
     203}
     204
     205/**
     206 * Port I/O Handler for PCI address OUT operations.
     207 *
     208 * @returns VBox status code.
     209 *
     210 * @param   pDevIns     The device instance.
     211 * @param   pvUser      User argument - ignored.
     212 * @param   uPort       Port number used for the OUT operation.
     213 * @param   u32         The value to output.
     214 * @param   cb          The value size in bytes.
     215 */
    161216PDMBOTHCBDECL(int)  ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
    162217{
     218    Log(("ich9pciIOPortAddressWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
     219    NOREF(pvUser);
     220    if (cb == 4)
     221    {
     222        PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     223        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
     224        pThis->uConfigReg = u32 & ~3; /* Bits 0-1 are reserved and we silently clear them */
     225        PCI_UNLOCK(pDevIns);
     226    }
     227    return VINF_SUCCESS;
     228}
     229
     230/**
     231 * Port I/O Handler for PCI address IN operations.
     232 *
     233 * @returns VBox status code.
     234 *
     235 * @param   pDevIns     The device instance.
     236 * @param   pvUser      User argument - ignored.
     237 * @param   uPort       Port number used for the IN operation.
     238 * @param   pu32        Where to store the result.
     239 * @param   cb          Number of bytes read.
     240 */
     241PDMBOTHCBDECL(int)  ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     242{
     243    NOREF(pvUser);
     244    if (cb == 4)
     245    {
     246        PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     247        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
     248        *pu32 = pThis->uConfigReg;
     249        PCI_UNLOCK(pDevIns);
     250        Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32));
     251        return VINF_SUCCESS;
     252    }
     253
     254    Log(("ich9pciIOPortAddressRead: Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", Port, cb));
     255
     256    return VERR_IOM_IOPORT_UNUSED;
     257}
     258
     259static int ich9pciDataWrite(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
     260{
     261    uint8_t iBus, iDevice;
     262    uint32_t uConfigReg;
     263
     264    Log(("ich9pciDataWrite: addr=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
     265
     266    if (!(pGlobals->uConfigReg & (1 << 31)))
     267        return VINF_SUCCESS;
     268
     269    if ((pGlobals->uConfigReg & 0x3) != 0)
     270        return VINF_SUCCESS;
     271
     272    /* Compute destination device */
     273    iBus = (pGlobals->uConfigReg >> 16) & 0xff;
     274    iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
     275    /* And config register */
     276    uConfigReg = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
     277    if (iBus != 0)
     278    {
     279        if (pGlobals->aPciBus.cBridges)
     280        {
     281#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
     282            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, iBus);
     283            if (pBridgeDevice)
     284            {
     285                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
     286                pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, uConfigReg, val, len);
     287            }
     288#else
     289            return VINF_IOM_HC_IOPORT_WRITE;
     290#endif
     291        }
     292    }
     293    else
     294    {
     295        if (pGlobals->aPciBus.apDevices[iDevice])
     296        {
     297#ifdef IN_RING3
     298            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[iDevice];
     299            Log(("ich9pciConfigWrite: %s: addr=%02x val=%08x len=%d\n", aDev->name, uConfigReg, val, len));
     300            aDev->Int.s.pfnConfigWrite(aDev, uConfigReg, val, len);
     301#else
     302            return VINF_IOM_HC_IOPORT_WRITE;
     303#endif
     304        }
     305    }
     306    return VINF_SUCCESS;
     307}
     308
     309/**
     310 * Port I/O Handler for PCI data OUT operations.
     311 *
     312 * @returns VBox status code.
     313 *
     314 * @param   pDevIns     The device instance.
     315 * @param   pvUser      User argument - ignored.
     316 * @param   uPort       Port number used for the OUT operation.
     317 * @param   u32         The value to output.
     318 * @param   cb          The value size in bytes.
     319 */
     320PDMBOTHCBDECL(int)  ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
     321{
     322    Log(("pciIOPortDataWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
     323    NOREF(pvUser);
     324    int rc = VINF_SUCCESS;
     325    if (!(Port % cb))
     326    {
     327        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
     328        rc = ich9pciDataWrite(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32, cb);
     329        PCI_UNLOCK(pDevIns);
     330    }
     331    else
     332        AssertMsgFailed(("Unaligned write to port %#x u32=%#x cb=%d\n", Port, u32, cb));
     333    return rc;
     334}
     335
     336static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int len, uint32_t *pu32)
     337{
     338    uint8_t iBus, iDevice;
     339    uint32_t uConfigReg;
     340
     341    *pu32 = 0xffffffff;
     342
     343    if (!(pGlobals->uConfigReg & (1 << 31)))
     344        return VINF_SUCCESS;
     345
     346    if ((pGlobals->uConfigReg & 0x3) != 0)
     347        return VINF_SUCCESS;
     348
     349    /* Compute destination device */
     350    iBus = (pGlobals->uConfigReg >> 16) & 0xff;
     351    iDevice = (pGlobals->uConfigReg >> 8) & 0xff;
     352    /* And config register */
     353    uConfigReg = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
     354    if (iBus != 0)
     355    {
     356        if (pGlobals->aPciBus.cBridges)
     357        {
     358#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
     359            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, iBus);
     360            if (pBridgeDevice)
     361            {
     362                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
     363                *pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, uConfigReg, len);
     364            }
     365#else
     366            return VINF_IOM_HC_IOPORT_READ;
     367#endif
     368        }
     369    }
     370    else
     371    {
     372        if (pGlobals->aPciBus.apDevices[iDevice])
     373        {
     374#ifdef IN_RING3
     375            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[iDevice];
     376            *pu32 = aDev->Int.s.pfnConfigRead(aDev, uConfigReg, len);
     377            Log(("ich9pciConfigRead: %s: addr=%02x val=%08x len=%d\n", aDev->name, uConfigReg, *pu32, len));
     378#else
     379            return VINF_IOM_HC_IOPORT_READ;
     380#endif
     381        }
     382    }
     383
     384    return VINF_SUCCESS;
     385}
     386
     387/**
     388 * Port I/O Handler for PCI data IN operations.
     389 *
     390 * @returns VBox status code.
     391 *
     392 * @param   pDevIns     The device instance.
     393 * @param   pvUser      User argument - ignored.
     394 * @param   uPort       Port number used for the IN operation.
     395 * @param   pu32        Where to store the result.
     396 * @param   cb          Number of bytes read.
     397 */
     398PDMBOTHCBDECL(int)  ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     399{
     400    NOREF(pvUser);
     401    if (!(Port % cb))
     402    {
     403        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
     404        int rc = ich9pciDataRead(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, cb, pu32);
     405        PCI_UNLOCK(pDevIns);
     406        Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x (%Rrc)\n", Port, cb, *pu32, rc));
     407        return rc;
     408    }
     409    AssertMsgFailed(("Unaligned read from port %#x cb=%d\n", Port, cb));
     410    return VERR_IOM_IOPORT_UNUSED;
     411}
     412
     413static inline int ich9pciSlot2ApicIrq(uint8_t uSlot, int irq_num)
     414{
     415    return (irq_num + uSlot) & 7;
     416}
     417
     418static inline void ich9pciApicLevelUp(PPCIGLOBALS pGlobals, int irq_num)
     419{
     420    ASMAtomicIncU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
     421}
     422
     423static inline void ich9pciApicLevelDown(PPCIGLOBALS pGlobals, int irq_num)
     424{
     425    ASMAtomicDecU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
     426}
     427
     428
     429static void ich9pciApicSetIrq(PPCIBUS pBus, uint8_t uDevFn, PCIDevice *pPciDev, int irq_num1, int iLevel, int iForcedIrq)
     430{
     431    /* This is only allowed to be called with a pointer to the root bus. */
     432    AssertMsg(pBus->iBus == 0, ("iBus=%u\n", pBus->iBus));
     433
     434    if (iForcedIrq == -1)
     435    {
     436        int apic_irq, apic_level;
     437        PPCIGLOBALS pGlobals = PCIROOTBUS_2_PCIGLOBALS(pBus);
     438        int irq_num = ich9pciSlot2ApicIrq(uDevFn >> 3, irq_num1);
     439
     440        if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH)
     441            ich9pciApicLevelUp(pGlobals, irq_num);
     442        else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW)
     443            ich9pciApicLevelDown(pGlobals, irq_num);
     444
     445        apic_irq = irq_num + 0x10;
     446        apic_level = pGlobals->uaPciApicIrqLevels[irq_num] != 0;
     447        Log3(("ich9pciApicSetIrq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d\n",
     448              R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
     449        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
     450
     451        if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
     452        {
     453            /**
     454             *  we raised it few lines above, as PDM_IRQ_LEVEL_FLIP_FLOP has
     455             * PDM_IRQ_LEVEL_HIGH bit set
     456             */
     457            ich9pciApicLevelDown(pGlobals, irq_num);
     458            pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
     459            apic_level = pGlobals->uaPciApicIrqLevels[irq_num] != 0;
     460            Log3(("ich9pciApicSetIrq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d (flop)\n",
     461                  R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
     462            pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
     463        }
     464    } else {
     465        Log3(("ich9pciApicSetIrq: %s: irq_num1=%d level=%d acpi_irq=%d\n",
     466              R3STRING(pPciDev->name), irq_num1, iLevel, iForcedIrq));
     467        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), iForcedIrq, iLevel);
     468    }
     469}
     470
     471static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel)
     472{
     473    PPCIBUS     pBus =     &pGlobals->aPciBus;
     474    const bool  fIsAcpiDevice = PCIDevGetDeviceId(pPciDev) == 0x7113;
     475
     476    /* Check if the state changed. */
     477    if (pPciDev->Int.s.uIrqPinState != iLevel)
     478    {
     479        pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
     480
     481        /* Send interrupt to I/O APIC only now. */
     482        if (fIsAcpiDevice)
     483            /*
     484             * ACPI needs special treatment since SCI is hardwired and
     485             * should not be affected by PCI IRQ routing tables at the
     486             * same time SCI IRQ is shared in PCI sense hence this
     487             * kludge (i.e. we fetch the hardwired value from ACPIs
     488             * PCI device configuration space).
     489             */
     490            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, PCIDevGetInterruptLine(pPciDev));
     491        else
     492            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, iIrq, iLevel, -1);
     493    }
     494}
     495
     496#ifdef IN_RING3
     497DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus)
     498{
     499    /* Search for a fitting bridge. */
     500    for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
     501    {
     502        /*
     503         * Examine secondary and subordinate bus number.
     504         * If the target bus is in the range we pass the request on to the bridge.
     505         */
     506        PPCIDEVICE pBridgeTemp = pBus->papBridgesR3[iBridge];
     507        AssertMsg(pBridgeTemp && pBridgeTemp->Int.s.fPciToPciBridge,
     508                  ("Device is not a PCI bridge but on the list of PCI bridges\n"));
     509
     510        if (   iBus >= pBridgeTemp->config[VBOX_PCI_SECONDARY_BUS]
     511            && iBus <= pBridgeTemp->config[VBOX_PCI_SUBORDINATE_BUS])
     512            return pBridgeTemp;
     513    }
     514
     515    /* Nothing found. */
     516    return NULL;
     517}
     518
     519/// @todo: simplify
     520static void ich9pciUpdateMappings(PCIDevice *d)
     521{
     522    PPCIBUS pBus = d->Int.s.CTX_SUFF(pBus);
     523    int cmd, i;
     524    uint32_t last_addr, new_addr, config_ofs;
     525
     526    cmd = PCIDevGetCommand(d);
     527    for (i = 0; i < PCI_NUM_REGIONS; i++) {
     528        PCIIORegion* r = &d->Int.s.aIORegions[i];
     529        if (i == PCI_ROM_SLOT) {
     530            config_ofs = 0x30;
     531        } else {
     532            config_ofs = 0x10 + i * 4;
     533        }
     534        if (r->size != 0) {
     535            if (r->type & PCI_ADDRESS_SPACE_IO) {
     536                if (cmd & PCI_COMMAND_IOACCESS) {
     537                    new_addr = ich9pciConfigRead(d, config_ofs, 4);
     538                    new_addr = new_addr & ~(r->size - 1);
     539                    last_addr = new_addr + r->size - 1;
     540                    /* NOTE: we have only 64K ioports on PC */
     541                    if (last_addr <= new_addr || new_addr == 0 ||
     542                        last_addr >= 0x10000) {
     543                        new_addr = ~0U;
     544                    }
     545                } else {
     546                    new_addr = ~0U;
     547                }
     548            } else {
     549                if (cmd & PCI_COMMAND_MEMACCESS) {
     550                    new_addr = ich9pciConfigRead(d, config_ofs, 4);
     551                    /* the ROM slot has a specific enable bit */
     552                    if (i == PCI_ROM_SLOT && !(new_addr & 1))
     553                        goto no_mem_map;
     554                    new_addr = new_addr & ~(r->size - 1);
     555                    last_addr = new_addr + r->size - 1;
     556                    /* NOTE: we do not support wrapping */
     557                    /* XXX: as we cannot support really dynamic
     558                       mappings, we handle specific values as invalid
     559                       mappings. */
     560                    if (last_addr <= new_addr || new_addr == 0 ||
     561                        last_addr == ~0U) {
     562                        new_addr = ~0U;
     563                    }
     564                } else {
     565                no_mem_map:
     566                    new_addr = ~0U;
     567                }
     568            }
     569            /* now do the real mapping */
     570            if (new_addr != r->addr) {
     571                if (r->addr != ~0U) {
     572                    if (r->type & PCI_ADDRESS_SPACE_IO) {
     573                        int devclass;
     574                        /* NOTE: specific hack for IDE in PC case:
     575                           only one byte must be mapped. */
     576                        devclass = d->config[0x0a] | (d->config[0x0b] << 8);
     577                        if (devclass == 0x0101 && r->size == 4) {
     578                            int rc = PDMDevHlpIOPortDeregister(d->pDevIns, r->addr + 2, 1);
     579                            AssertRC(rc);
     580                        } else {
     581                            int rc = PDMDevHlpIOPortDeregister(d->pDevIns, r->addr, r->size);
     582                            AssertRC(rc);
     583                        }
     584                    } else {
     585                        RTGCPHYS GCPhysBase = r->addr;
     586                        int rc;
     587                        if (pBus->pPciHlpR3->pfnIsMMIO2Base(pBus->pDevInsR3, d->pDevIns, GCPhysBase))
     588                        {
     589                            /* unmap it. */
     590                            rc = r->map_func(d, i, NIL_RTGCPHYS, r->size, (PCIADDRESSSPACE)(r->type));
     591                            AssertRC(rc);
     592                            rc = PDMDevHlpMMIO2Unmap(d->pDevIns, i, GCPhysBase);
     593                        }
     594                        else
     595                            rc = PDMDevHlpMMIODeregister(d->pDevIns, GCPhysBase, r->size);
     596                        AssertMsgRC(rc, ("rc=%Rrc d=%s i=%d GCPhysBase=%RGp size=%#x\n", rc, d->name, i, GCPhysBase, r->size));
     597                    }
     598                }
     599                r->addr = new_addr;
     600                if (r->addr != ~0U) {
     601                    int rc = r->map_func(d, i,
     602                                         r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : 0),
     603                                         r->size, (PCIADDRESSSPACE)(r->type));
     604                    AssertRC(rc);
     605                }
     606            }
     607        }
     608    }
     609}
     610
     611static DECLCALLBACK(int) ich9pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
     612{
     613    PPCIBUS     pBus = DEVINS_2_PCIBUS(pDevIns);
     614
     615    /*
     616     * Check input.
     617     */
     618    if (    !pszName
     619        ||  !pPciDev
     620        ||  iDev >= (int)RT_ELEMENTS(pBus->apDevices)
     621        )
     622    {
     623        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
     624        return VERR_INVALID_PARAMETER;
     625    }
     626
     627    /*
     628     * Register the device.
     629     */
     630    return ich9pciRegisterInternal(pBus, iDev, pPciDev, pszName);
     631}
     632
     633static DECLCALLBACK(int) ich9pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
     634{
    163635    return 0;
    164636}
    165637
    166 PDMBOTHCBDECL(int)  ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
    167 {
    168     return 0;
    169 }
    170 
    171 PDMBOTHCBDECL(int)  ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
    172 {
    173     return 0;
    174 }
    175 
    176 PDMBOTHCBDECL(int)  ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
    177 {
    178     return 0;
    179 }
    180 
    181 #ifdef IN_RING3
    182 DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus);
    183 #endif
    184 
    185 #ifdef IN_RING3
    186 
    187 static DECLCALLBACK(int) ich9pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
    188 {
    189     return 0;
    190 }
    191 
    192 static DECLCALLBACK(int) ich9pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
    193 {
    194     return 0;
    195 }
    196 
    197638static DECLCALLBACK(int) ich9pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
    198639{
    199     return 0;
     640    /*
     641     * Validate.
     642     */
     643    AssertMsgReturn(   enmType == PCI_ADDRESS_SPACE_MEM
     644                    || enmType == PCI_ADDRESS_SPACE_IO
     645                    || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH,
     646                    ("Invalid enmType=%#x? Or was this a bitmask after all...\n", enmType),
     647                    VERR_INVALID_PARAMETER);
     648    AssertMsgReturn((unsigned)iRegion < PCI_NUM_REGIONS,
     649                    ("Invalid iRegion=%d PCI_NUM_REGIONS=%d\n", iRegion, PCI_NUM_REGIONS),
     650                    VERR_INVALID_PARAMETER);
     651    int iLastSet = ASMBitLastSetU32(cbRegion);
     652    AssertMsgReturn(    iLastSet != 0
     653                    &&  RT_BIT_32(iLastSet - 1) == cbRegion,
     654                    ("Invalid cbRegion=%#x iLastSet=%#x (not a power of 2 or 0)\n", cbRegion, iLastSet),
     655                    VERR_INVALID_PARAMETER);
     656
     657    /*
     658     * Register the I/O region.
     659     */
     660    PPCIIOREGION pRegion = &pPciDev->Int.s.aIORegions[iRegion];
     661    pRegion->addr        = ~0U;
     662    pRegion->size        = cbRegion;
     663    pRegion->type        = enmType;
     664    pRegion->map_func    = pfnCallback;
     665
     666    /* Set type in the config space. */
     667    uint32_t u32Address = 0x10 + iRegion * 4;
     668    uint32_t u32Value   =   (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH ? (1 << 3) : 0)
     669                          | (enmType == PCI_ADDRESS_SPACE_IO ? 1 : 0);
     670    *(uint32_t *)(pPciDev->config + u32Address) = RT_H2LE_U32(u32Value);
     671
     672    return VINF_SUCCESS;
    200673}
    201674
     
    203676                                                    PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
    204677{
     678    if (ppfnReadOld)
     679        *ppfnReadOld = pPciDev->Int.s.pfnConfigRead;
     680    pPciDev->Int.s.pfnConfigRead  = pfnRead;
     681
     682    if (ppfnWriteOld)
     683        *ppfnWriteOld = pPciDev->Int.s.pfnConfigWrite;
     684    pPciDev->Int.s.pfnConfigWrite = pfnWrite;
    205685}
    206686
     
    223703     * Iterate thru all the devices.
    224704     */
    225     for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
    226     {
    227         PPCIDEVICE pDev = pBus->devices[i];
     705    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
     706    {
     707        PPCIDEVICE pDev = pBus->apDevices[i];
    228708        if (pDev)
    229709        {
     
    286766}
    287767
     768static void ich9pciBiosInitDevice(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
     769{
     770}
     771
     772static const uint8_t auPciIrqs[4] = { 11, 9, 11, 9 };
     773
    288774static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
    289775{
    290     return 0;
     776    unsigned    i;
     777    uint8_t     elcr[2] = {0, 0};
     778    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     779    PVM         pVM = PDMDevHlpGetVM(pDevIns);
     780    Assert(pVM);
     781
     782    /*
     783     * Set the start addresses.
     784     */
     785    pGlobals->uPciBiosIo  = 0xd000;
     786    pGlobals->uPciBiosMmio = UINT32_C(0xf0000000);
     787    pGlobals->uBus = 0;
     788
     789    /*
     790     * Activate IRQ mappings.
     791     */
     792    for (i = 0; i < 4; i++)
     793    {
     794        uint8_t irq = auPciIrqs[i];
     795        /* Set to trigger level. */
     796        elcr[irq >> 3] |= (1 << (irq & 7));
     797    }
     798
     799    /* Tell to the PIC. */
     800    VBOXSTRICTRC rcStrict = IOMIOPortWrite(pVM, 0x4d0, elcr[0], sizeof(uint8_t));
     801    if (rcStrict == VINF_SUCCESS)
     802        rcStrict = IOMIOPortWrite(pVM, 0x4d1, elcr[1], sizeof(uint8_t));
     803    if (rcStrict != VINF_SUCCESS)
     804    {
     805        AssertMsgFailed(("Writing to PIC failed! rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     806        return RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR : VBOXSTRICTRC_VAL(rcStrict);
     807    }
     808
     809    /*
     810     * Init the devices.
     811     */
     812    for (i = 0; i < 256; i++)
     813    {
     814        uint8_t aBridgePositions[256];
     815
     816        memset(aBridgePositions, 0, sizeof(aBridgePositions));
     817        Log2(("PCI: Initializing device %d (%#x)\n",
     818              i, 0x80000000 | (i << 8)));
     819        ich9pciBiosInitDevice(pGlobals, 0, i, 0, aBridgePositions);
     820    }
     821
     822    return VINF_SUCCESS;
    291823}
    292824
    293825static DECLCALLBACK(uint32_t) ich9pciConfigRead(PCIDevice *aDev, uint32_t u32Address, unsigned len)
    294826{
    295     if (u32Address + len >= 256)
    296     {
    297         Assert(false);
    298         return 0;
    299     }
    300 
     827    AssertMsgReturn(u32Address + len <= 256, ("Read after end of PCI config space\n"),
     828                    0);
    301829    switch (len)
    302830    {
     
    312840
    313841
    314 static DECLCALLBACK(void) ich9pciConfigWrite(PCIDevice *aDev, uint32_t u32Address, uint32_t val, unsigned len)
    315 {
    316     // @todo: write me
     842/**
     843 * See paragraph 7.5 of PCI Express specification (p. 349) for definition of
     844 * registers and their writability policy.
     845 */
     846static DECLCALLBACK(void) ich9pciConfigWrite(PCIDevice *aDev, uint32_t u32Address,
     847                                             uint32_t val, unsigned len)
     848{
     849    /* Fast case - update one of BARs or ROM address, 'while' only for 'break' */
     850    while (len == 4 &&
     851           (u32Address >= VBOX_PCI_BASE_ADDRESS_0 &&
     852            u32Address < VBOX_PCI_BASE_ADDRESS_0 + 6 * 4)
     853           ||
     854           (u32Address >= VBOX_PCI_ROM_ADDRESS && u32Address < VBOX_PCI_ROM_ADDRESS+4))
     855    {
     856        PCIIORegion *region;
     857        int reg, regionSize;
     858
     859        reg = (u32Address >= VBOX_PCI_ROM_ADDRESS) ? PCI_ROM_SLOT : (u32Address - VBOX_PCI_BASE_ADDRESS_0) >> 2;
     860        region = &aDev->Int.s.aIORegions[reg];
     861        regionSize = region->size;
     862        if (regionSize == 0)
     863            break;
     864        /* compute the stored value */
     865        if (reg == PCI_ROM_SLOT) {
     866            /* keep ROM enable bit */
     867            val &= (~(regionSize - 1)) | 1;
     868        } else {
     869            val &= ~(regionSize - 1);
     870            val |= region->type;
     871        }
     872        *(uint32_t *)(aDev->config + u32Address) = RT_H2LE_U32(val);
     873        ich9pciUpdateMappings(aDev);
     874        return;
     875    }
     876
     877    uint32_t addr = u32Address;
     878    bool fUpdateMappings = false;
     879    for (uint32_t i = 0; i < len; i++)
     880    {
     881        bool fWritable = false;
     882        switch (PCIDevGetHeaderType(aDev))
     883        {
     884            case 0x00: /* normal device */
     885            case 0x80: /* multi-function device */
     886                switch (addr)
     887                {
     888                    /* Read-only registers, see  */
     889                    case VBOX_PCI_VENDOR_ID: case VBOX_PCI_VENDOR_ID+1:
     890                    case VBOX_PCI_DEVICE_ID: case VBOX_PCI_DEVICE_ID+1:
     891                    case VBOX_PCI_REVISION_ID:
     892                    case VBOX_PCI_CLASS_PROG:
     893                    case VBOX_PCI_CLASS_SUB:
     894                    case VBOX_PCI_CLASS_BASE:
     895                    case VBOX_PCI_HEADER_TYPE:
     896                    case VBOX_PCI_BASE_ADDRESS_0: case VBOX_PCI_BASE_ADDRESS_0+1: case VBOX_PCI_BASE_ADDRESS_0+2: case VBOX_PCI_BASE_ADDRESS_0+3:
     897                    case VBOX_PCI_BASE_ADDRESS_1: case VBOX_PCI_BASE_ADDRESS_1+1: case VBOX_PCI_BASE_ADDRESS_1+2: case VBOX_PCI_BASE_ADDRESS_1+3:
     898                    case VBOX_PCI_BASE_ADDRESS_2: case VBOX_PCI_BASE_ADDRESS_2+1: case VBOX_PCI_BASE_ADDRESS_2+2: case VBOX_PCI_BASE_ADDRESS_2+3:
     899                    case VBOX_PCI_BASE_ADDRESS_3: case VBOX_PCI_BASE_ADDRESS_3+1: case VBOX_PCI_BASE_ADDRESS_3+2: case VBOX_PCI_BASE_ADDRESS_3+3:
     900                    case VBOX_PCI_BASE_ADDRESS_4: case VBOX_PCI_BASE_ADDRESS_4+1: case VBOX_PCI_BASE_ADDRESS_4+2: case VBOX_PCI_BASE_ADDRESS_4+3:
     901                    case VBOX_PCI_BASE_ADDRESS_5: case VBOX_PCI_BASE_ADDRESS_5+1: case VBOX_PCI_BASE_ADDRESS_5+2: case VBOX_PCI_BASE_ADDRESS_5+3:
     902                    case VBOX_PCI_SUBSYSTEM_VENDOR_ID: case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1:
     903                    case VBOX_PCI_SUBSYSTEM_ID: case VBOX_PCI_SUBSYSTEM_ID+1:
     904                    case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS+1: case VBOX_PCI_ROM_ADDRESS+2: case VBOX_PCI_ROM_ADDRESS+3:
     905                    case VBOX_PCI_CAPABILITY_LIST:
     906                    case VBOX_PCI_INTERRUPT_PIN:
     907                        fWritable = false;
     908                        break;
     909                    /* Others can be written */
     910                    default:
     911                        fWritable = true;
     912                        break;
     913                }
     914                break;
     915            default:
     916            case 0x01: /* bridge */
     917                switch (addr)
     918                {
     919                    /* Read-only registers */
     920                    case VBOX_PCI_VENDOR_ID: case VBOX_PCI_VENDOR_ID+1:
     921                    case VBOX_PCI_DEVICE_ID: case VBOX_PCI_DEVICE_ID+1:
     922                    case VBOX_PCI_REVISION_ID:
     923                    case VBOX_PCI_CLASS_PROG:
     924                    case VBOX_PCI_CLASS_SUB:
     925                    case VBOX_PCI_CLASS_BASE:
     926                    case VBOX_PCI_HEADER_TYPE:
     927                    case VBOX_PCI_ROM_ADDRESS_BR: case VBOX_PCI_ROM_ADDRESS_BR+1: case VBOX_PCI_ROM_ADDRESS_BR+2: case VBOX_PCI_ROM_ADDRESS_BR+3:
     928                    case VBOX_PCI_INTERRUPT_PIN:
     929                        fWritable = false;
     930                        break;
     931                    default:
     932                        fWritable = true;
     933                        break;
     934            }
     935            break;
     936        }
     937
     938        switch (addr)
     939        {
     940            case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */
     941                fUpdateMappings = true;
     942                aDev->config[addr] = val;
     943                break;
     944            case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */
     945                /* don't change reserved bits (11-15) */
     946                val &= UINT32_C(~0xf8);
     947                fUpdateMappings = true;
     948                aDev->config[addr] = val;
     949                break;
     950            case VBOX_PCI_STATUS:  /* Status register, bits 0-7. */
     951                /* don't change read-only bits => actually all lower bits are read-only */
     952                val &= UINT32_C(~0xff);
     953                /* status register, low part: clear bits by writing a '1' to the corresponding bit */
     954                aDev->config[addr] &= ~val;
     955                break;
     956            case VBOX_PCI_STATUS+1:  /* Status register, bits 8-15. */
     957                /* don't change read-only bits */
     958                val &= UINT32_C(~0x06);
     959                /* status register, high part: clear bits by writing a '1' to the corresponding bit */
     960                aDev->config[addr] &= ~val;
     961                break;
     962            default:
     963                if (fWritable)
     964                    aDev->config[addr] = val;
     965        }
     966        addr++;
     967        val >>= 8;
     968    }
     969
     970    if (fUpdateMappings)
     971        /* if the command register is modified, we must modify the mappings */
     972        ich9pciUpdateMappings(aDev);
    317973}
    318974
     
    3481004    },
    3491005};
     1006
    3501007static int assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName)
    3511008{
     
    3611018
    3621019    /* Otherwise when assigning a slot, we need to make sure all its functions are available */
    363     for (int iPos = 0; iPos < (int)RT_ELEMENTS(pBus->devices); iPos += 8)
    364         if (        !pBus->devices[iPos]
    365                 &&  !pBus->devices[iPos + 1]
    366                 &&  !pBus->devices[iPos + 2]
    367                 &&  !pBus->devices[iPos + 3]
    368                 &&  !pBus->devices[iPos + 4]
    369                 &&  !pBus->devices[iPos + 5]
    370                 &&  !pBus->devices[iPos + 6]
    371                 &&  !pBus->devices[iPos + 7])
     1020    for (int iPos = 0; iPos < (int)RT_ELEMENTS(pBus->apDevices); iPos += 8)
     1021        if (        !pBus->apDevices[iPos]
     1022                &&  !pBus->apDevices[iPos + 1]
     1023                &&  !pBus->apDevices[iPos + 2]
     1024                &&  !pBus->apDevices[iPos + 3]
     1025                &&  !pBus->apDevices[iPos + 4]
     1026                &&  !pBus->apDevices[iPos + 5]
     1027                &&  !pBus->apDevices[iPos + 6]
     1028                &&  !pBus->apDevices[iPos + 7])
    3721029        {
    3731030            pPciDev->Int.s.fRequestedDevFn = false;
     
    3801037static bool hasHardAssignedDevsInSlot(PPCIBUS pBus, int iSlot)
    3811038{
    382     PCIDevice** aSlot = &pBus->devices[iSlot << 3];
     1039    PCIDevice** aSlot = &pBus->apDevices[iSlot << 3];
    3831040
    3841041    return    (aSlot[0] && aSlot[0]->Int.s.fRequestedDevFn)
     
    4131070     */
    4141071    if (pPciDev->Int.s.fRequestedDevFn &&
    415         pBus->devices[iDev]            &&
    416         pBus->devices[iDev]->Int.s.fRequestedDevFn)
     1072        pBus->apDevices[iDev]            &&
     1073        pBus->apDevices[iDev]->Int.s.fRequestedDevFn)
    4171074    {
    4181075        /*
    419          * Smth like hasHardAssignedDevsInSlot(pBus, iDev >> 3) shall be use to make 
    420          * it compatible with DevPCI.cpp version, but this way we cannot assign 
     1076         * Smth like hasHardAssignedDevsInSlot(pBus, iDev >> 3) shall be use to make
     1077         * it compatible with DevPCI.cpp version, but this way we cannot assign
    4211078         * in accordance with the chipset spec.
    4221079         */
    4231080        AssertReleaseMsgFailed(("Configuration error:'%s' and '%s' are both configured as device %d\n",
    424                                  pszName, pBus->devices[iDev]->name, iDev));
     1081                                 pszName, pBus->apDevices[iDev]->name, iDev));
    4251082        return VERR_INTERNAL_ERROR;
    4261083    }
    4271084
    428     if (pBus->devices[iDev])
     1085    if (pBus->apDevices[iDev])
    4291086    {
    4301087        /* if we got here, we shall (and usually can) relocate the device */
    431         int iRelDev = assignPosition(pBus, pBus->devices[iDev], pBus->devices[iDev]->name);
     1088        int iRelDev = assignPosition(pBus, pBus->apDevices[iDev], pBus->apDevices[iDev]->name);
    4321089        if (iRelDev < 0 || iRelDev == iDev)
    4331090        {
     
    4381095        for (int i = 0; i < 8; i++)
    4391096        {
    440             if (!pBus->devices[iDev + i])
     1097            if (!pBus->apDevices[iDev + i])
    4411098                continue;
    442             Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->devices[iDev + i]->name, iDev + i, iRelDev + i));
    443             pBus->devices[iRelDev + i] = pBus->devices[iDev + i];
    444             pBus->devices[iRelDev + i]->devfn = i;
    445             pBus->devices[iDev + i] = NULL;
     1099            Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->apDevices[iDev + i]->name, iDev + i, iRelDev + i));
     1100            pBus->apDevices[iRelDev + i] = pBus->apDevices[iDev + i];
     1101            pBus->apDevices[iRelDev + i]->devfn = i;
     1102            pBus->apDevices[iDev + i] = NULL;
    4461103        }
    4471104    }
     
    4571114    pPciDev->Int.s.pfnConfigRead    = ich9pciConfigRead;
    4581115    pPciDev->Int.s.pfnConfigWrite   = ich9pciConfigWrite;
    459     pBus->devices[iDev]             = pPciDev;
     1116    pBus->apDevices[iDev]           = pPciDev;
    4601117    if (pPciDev->Int.s.fPciToPciBridge)
    4611118    {
    462         AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->devices), ("Number of bridges exceeds the number of possible devices on the bus\n"));
     1119        AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->apDevices), ("Number of bridges exceeds the number of possible devices on the bus\n"));
    4631120        AssertMsg(pPciDev->Int.s.pfnBridgeConfigRead && pPciDev->Int.s.pfnBridgeConfigWrite,
    4641121                  ("device is a bridge but does not implement read/write functions\n"));
     
    5161173    memset(pGlobals, 0, sizeof(*pGlobals));
    5171174    /* And fill values */
    518     pGlobals->fUseIoApic          = fUseIoApic;
     1175    if (!fUseIoApic)
     1176        return PDMDEV_SET_ERROR(pDevIns, rc,
     1177                                N_("Must use IO-APIC with ICH9 chipset"));
    5191178    pGlobals->pDevInsR3 = pDevIns;
    5201179    pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     
    5241183    pGlobals->aPciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    5251184    pGlobals->aPciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    526     pGlobals->aPciBus.papBridgesR3 = (PPCIDEVICE *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPCIDEVICE) * RT_ELEMENTS(pGlobals->aPciBus.devices));
     1185    pGlobals->aPciBus.papBridgesR3 = (PPCIDEVICE *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPCIDEVICE) * RT_ELEMENTS(pGlobals->aPciBus.apDevices));
    5271186
    5281187    /*
     
    5641223     *   A2        SLA9M    NH82801IB
    5651224     */
    566     PCIDevSetVendorId(  &pBus->PciDev, 0x8086); /* Intel */
    567     PCIDevSetDeviceId(  &pBus->PciDev, 0x244e); /* Desktop */
    568     PCIDevSetRevisionId(&pBus->PciDev,   0x92); /* rev. A2 */
    569     PCIDevSetClassSub(  &pBus->PciDev,   0x00); /* Host/PCI bridge */
    570     PCIDevSetClassBase( &pBus->PciDev,   0x06); /* bridge */
    571     PCIDevSetHeaderType(&pBus->PciDev,   0x00);
    572 
    573     pBus->PciDev.pDevIns              = pDevIns;
    574     pBus->PciDev.Int.s.fRequestedDevFn= true;
     1225    PCIDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
     1226    PCIDevSetDeviceId(  &pBus->aPciDev, 0x244e); /* Desktop */
     1227    PCIDevSetRevisionId(&pBus->aPciDev,   0x92); /* rev. A2 */
     1228    PCIDevSetClassSub(  &pBus->aPciDev,   0x00); /* Host/PCI bridge */
     1229    PCIDevSetClassBase( &pBus->aPciDev,   0x06); /* bridge */
     1230    PCIDevSetHeaderType(&pBus->aPciDev,   0x00);
     1231
     1232    pBus->aPciDev.pDevIns               = pDevIns;
     1233    pBus->aPciDev.Int.s.fRequestedDevFn = true;
    5751234    /* We register Host<->PCI controller on the bus */
    576     ich9pciRegisterInternal(pBus, 0, &pBus->PciDev, "i82801");
     1235    ich9pciRegisterInternal(pBus, 0, &pBus->aPciDev, "i82801");
    5771236
    5781237    /** @todo: ther chipset devices shall be registered too */
     
    5871246static DECLCALLBACK(void) ich9pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    5881247{
     1248    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
     1249    PPCIBUS     pBus     = &pGlobals->aPciBus;
     1250    pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1251
     1252    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
     1253    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1254
     1255    /* Relocate RC pointers for the attached pci devices. */
     1256    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
     1257    {
     1258        if (pBus->apDevices[i])
     1259            pBus->apDevices[i]->Int.s.pBusRC += offDelta;
     1260    }
     1261
    5891262}
    5901263
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