~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Bus/DevPciIch9.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: DevPciIch9.cpp 35397 2011-01-03 23:11:50Z vboxsync $ */
 
2
/** @file
 
3
 * DevPCI - ICH9 southbridge PCI bus emulation Device.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2010 Oracle Corporation
 
8
 *
 
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
10
 * available from http://www.virtualbox.org. This file is free software;
 
11
 * you can redistribute it and/or modify it under the terms of the GNU
 
12
 * General Public License (GPL) as published by the Free Software
 
13
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
14
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
15
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
16
 */
 
17
 
 
18
/*******************************************************************************
 
19
 *   Header Files                                                              *
 
20
 *******************************************************************************/
 
21
#define LOG_GROUP LOG_GROUP_DEV_PCI
 
22
/* Hack to get PCIDEVICEINT declare at the right point - include "PCIInternal.h". */
 
23
#define PCI_INCLUDE_PRIVATE
 
24
#include <VBox/pci.h>
 
25
#include <VBox/msi.h>
 
26
#include <VBox/vmm/pdmdev.h>
 
27
#include <iprt/asm.h>
 
28
#include <iprt/assert.h>
 
29
#include <iprt/string.h>
 
30
#ifdef IN_RING3
 
31
#include <iprt/alloc.h>
 
32
#endif
 
33
 
 
34
#include "VBoxDD.h"
 
35
 
 
36
#include "MsiCommon.h"
 
37
 
 
38
/**
 
39
 * PCI Bus instance.
 
40
 */
 
41
typedef struct PCIBus
 
42
{
 
43
    /** Bus number. */
 
44
    int32_t             iBus;
 
45
    /** Number of bridges attached to the bus. */
 
46
    uint32_t            cBridges;
 
47
 
 
48
    /** Array of PCI devices. We assume 32 slots, each with 8 functions. */
 
49
    R3PTRTYPE(PPCIDEVICE)   apDevices[256];
 
50
    /** Array of bridges attached to the bus. */
 
51
    R3PTRTYPE(PPCIDEVICE *) papBridgesR3;
 
52
 
 
53
    /** R3 pointer to the device instance. */
 
54
    PPDMDEVINSR3        pDevInsR3;
 
55
    /** Pointer to the PCI R3  helpers. */
 
56
    PCPDMPCIHLPR3       pPciHlpR3;
 
57
 
 
58
    /** R0 pointer to the device instance. */
 
59
    PPDMDEVINSR0        pDevInsR0;
 
60
    /** Pointer to the PCI R0 helpers. */
 
61
    PCPDMPCIHLPR0       pPciHlpR0;
 
62
 
 
63
    /** RC pointer to the device instance. */
 
64
    PPDMDEVINSRC        pDevInsRC;
 
65
    /** Pointer to the PCI RC helpers. */
 
66
    PCPDMPCIHLPRC       pPciHlpRC;
 
67
 
 
68
    /** The PCI device for the PCI bridge. */
 
69
    PCIDEVICE           aPciDev;
 
70
 
 
71
} PCIBUS, *PPCIBUS;
 
72
 
 
73
 
 
74
/** @def PCI_APIC_IRQ_PINS
 
75
 * Number of pins for interrupts if the APIC is used.
 
76
 */
 
77
#define PCI_APIC_IRQ_PINS 8
 
78
 
 
79
/**
 
80
 * PCI Globals - This is the host-to-pci bridge and the root bus.
 
81
 */
 
82
typedef struct
 
83
{
 
84
    /** R3 pointer to the device instance. */
 
85
    PPDMDEVINSR3        pDevInsR3;
 
86
    /** R0 pointer to the device instance. */
 
87
    PPDMDEVINSR0        pDevInsR0;
 
88
    /** RC pointer to the device instance. */
 
89
    PPDMDEVINSRC        pDevInsRC;
 
90
 
 
91
#if HC_ARCH_BITS == 64
 
92
    uint32_t            Alignment0;
 
93
#endif
 
94
 
 
95
    /** PCI bus which is attached to the host-to-PCI bridge. */
 
96
    PCIBUS              aPciBus;
 
97
 
 
98
 
 
99
    /** I/O APIC irq levels */
 
100
    volatile uint32_t   uaPciApicIrqLevels[PCI_APIC_IRQ_PINS];
 
101
 
 
102
#if 1 /* Will be moved into the BIOS soon. */
 
103
    /** The next I/O port address which the PCI BIOS will use. */
 
104
    uint32_t            uPciBiosIo;
 
105
    /** The next MMIO address which the PCI BIOS will use. */
 
106
    uint32_t            uPciBiosMmio;
 
107
    /** Actual bus number. */
 
108
    uint8_t             uBus;
 
109
#endif
 
110
    /* Physical address of PCI config space MMIO region */
 
111
    uint64_t            u64PciConfigMMioAddress;
 
112
    /* Length of PCI config space MMIO region */
 
113
    uint64_t            u64PciConfigMMioLength;
 
114
 
 
115
 
 
116
    /** Config register. */
 
117
    uint32_t            uConfigReg;
 
118
} PCIGLOBALS, *PPCIGLOBALS;
 
119
 
 
120
 
 
121
typedef struct {
 
122
    uint8_t  iBus;
 
123
    uint8_t  iDeviceFunc;
 
124
    uint16_t iRegister;
 
125
} PciAddress;
 
126
 
 
127
/*******************************************************************************
 
128
 *   Defined Constants And Macros                                              *
 
129
 *******************************************************************************/
 
130
 
 
131
/** @def VBOX_ICH9PCI_SAVED_STATE_VERSION
 
132
 * Saved state version of the ICH9 PCI bus device.
 
133
 */
 
134
#define VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI 1
 
135
#define VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI   2
 
136
#define VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI
 
137
 
 
138
/** Converts a bus instance pointer to a device instance pointer. */
 
139
#define PCIBUS_2_DEVINS(pPciBus)        ((pPciBus)->CTX_SUFF(pDevIns))
 
140
/** Converts a device instance pointer to a PCIGLOBALS pointer. */
 
141
#define DEVINS_2_PCIGLOBALS(pDevIns)    ((PPCIGLOBALS)(PDMINS_2_DATA(pDevIns, PPCIGLOBALS)))
 
142
/** Converts a device instance pointer to a PCIBUS pointer. */
 
143
#define DEVINS_2_PCIBUS(pDevIns)        ((PPCIBUS)(&PDMINS_2_DATA(pDevIns, PPCIGLOBALS)->aPciBus))
 
144
/** Converts a pointer to a PCI root bus instance to a PCIGLOBALS pointer.
 
145
 */
 
146
#define PCIROOTBUS_2_PCIGLOBALS(pPciBus)    ( (PPCIGLOBALS)((uintptr_t)(pPciBus) - RT_OFFSETOF(PCIGLOBALS, aPciBus)) )
 
147
 
 
148
 
 
149
/** @def PCI_LOCK
 
150
 * Acquires the PDM lock. This is a NOP if locking is disabled. */
 
151
/** @def PCI_UNLOCK
 
152
 * Releases the PDM lock. This is a NOP if locking is disabled. */
 
153
#define PCI_LOCK(pDevIns, rc) \
 
154
    do { \
 
155
        int rc2 = DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \
 
156
        if (rc2 != VINF_SUCCESS) \
 
157
            return rc2; \
 
158
    } while (0)
 
159
#define PCI_UNLOCK(pDevIns) \
 
160
    DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns)
 
161
 
 
162
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
 
163
 
 
164
RT_C_DECLS_BEGIN
 
165
 
 
166
PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
 
167
PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
 
168
PDMBOTHCBDECL(int)  ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
 
169
PDMBOTHCBDECL(int)  ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
 
170
PDMBOTHCBDECL(int)  ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
 
171
PDMBOTHCBDECL(int)  ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
 
172
PDMBOTHCBDECL(int)  ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
 
173
PDMBOTHCBDECL(int)  ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
 
174
 
 
175
RT_C_DECLS_END
 
176
 
 
177
/* Prototypes */
 
178
static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel);
 
179
#ifdef IN_RING3
 
180
static void ich9pcibridgeReset(PPDMDEVINS pDevIns);
 
181
static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName);
 
182
static void ich9pciUpdateMappings(PCIDevice *pDev);
 
183
static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PCIDevice *aDev, uint32_t u32Address, unsigned len);
 
184
DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus);
 
185
static void ich9pciBiosInitDevice(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions);
 
186
#endif
 
187
 
 
188
// See 7.2.2. PCI Express Enhanced Configuration Mechanism for details of address
 
189
// mapping, we take n=6 approach
 
190
DECLINLINE(void) ich9pciPhysToPciAddr(PPCIGLOBALS pGlobals, RTGCPHYS GCPhysAddr, PciAddress* pPciAddr)
 
191
{
 
192
    pPciAddr->iBus          = (GCPhysAddr >> 20) & ((1<<6)       - 1);
 
193
    pPciAddr->iDeviceFunc   = (GCPhysAddr >> 12) & ((1<<(5+3))   - 1); // 5 bits - device, 3 bits - function
 
194
    pPciAddr->iRegister     = (GCPhysAddr >>  0) & ((1<<(6+4+2)) - 1); // 6 bits - register, 4 bits - extended register, 2 bits -Byte Enable
 
195
}
 
196
 
 
197
DECLINLINE(void) ich9pciStateToPciAddr(PPCIGLOBALS pGlobals, RTGCPHYS addr, PciAddress* pPciAddr)
 
198
{
 
199
    pPciAddr->iBus         = (pGlobals->uConfigReg >> 16) & 0xff;
 
200
    pPciAddr->iDeviceFunc  = (pGlobals->uConfigReg >> 8) & 0xff;
 
201
    pPciAddr->iRegister    = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
 
202
}
 
203
 
 
204
PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
 
205
{
 
206
    ich9pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), pPciDev->devfn, pPciDev, iIrq, iLevel);
 
207
}
 
208
 
 
209
PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
 
210
{
 
211
    /*
 
212
     * The PCI-to-PCI bridge specification defines how the interrupt pins
 
213
     * are routed from the secondary to the primary bus (see chapter 9).
 
214
     * iIrq gives the interrupt pin the pci device asserted.
 
215
     * We change iIrq here according to the spec and call the SetIrq function
 
216
     * of our parent passing the device which asserted the interrupt instead of the device of the bridge.
 
217
     */
 
218
    PPCIBUS    pBus          = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
219
    PPCIDEVICE pPciDevBus    = pPciDev;
 
220
    int        iIrqPinBridge = iIrq;
 
221
    uint8_t    uDevFnBridge  = 0;
 
222
 
 
223
    /* Walk the chain until we reach the host bus. */
 
224
    do
 
225
    {
 
226
        uDevFnBridge  = pBus->aPciDev.devfn;
 
227
        iIrqPinBridge = ((pPciDevBus->devfn >> 3) + iIrqPinBridge) & 3;
 
228
 
 
229
        /* Get the parent. */
 
230
        pBus = pBus->aPciDev.Int.s.CTX_SUFF(pBus);
 
231
        pPciDevBus = &pBus->aPciDev;
 
232
    } while (pBus->iBus != 0);
 
233
 
 
234
    AssertMsgReturnVoid(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus));
 
235
    ich9pciSetIrqInternal(PCIROOTBUS_2_PCIGLOBALS(pBus), uDevFnBridge, pPciDev, iIrqPinBridge, iLevel);
 
236
}
 
237
 
 
238
/**
 
239
 * Port I/O Handler for PCI address OUT operations.
 
240
 *
 
241
 * @returns VBox status code.
 
242
 *
 
243
 * @param   pDevIns     The device instance.
 
244
 * @param   pvUser      User argument - ignored.
 
245
 * @param   uPort       Port number used for the OUT operation.
 
246
 * @param   u32         The value to output.
 
247
 * @param   cb          The value size in bytes.
 
248
 */
 
249
PDMBOTHCBDECL(int)  ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
 
250
{
 
251
    Log(("ich9pciIOPortAddressWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
 
252
    NOREF(pvUser);
 
253
    if (cb == 4)
 
254
    {
 
255
        PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
256
 
 
257
        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
 
258
        pThis->uConfigReg = u32 & ~3; /* Bits 0-1 are reserved and we silently clear them */
 
259
        PCI_UNLOCK(pDevIns);
 
260
    }
 
261
 
 
262
    return VINF_SUCCESS;
 
263
}
 
264
 
 
265
/**
 
266
 * Port I/O Handler for PCI address IN operations.
 
267
 *
 
268
 * @returns VBox status code.
 
269
 *
 
270
 * @param   pDevIns     The device instance.
 
271
 * @param   pvUser      User argument - ignored.
 
272
 * @param   uPort       Port number used for the IN operation.
 
273
 * @param   pu32        Where to store the result.
 
274
 * @param   cb          Number of bytes read.
 
275
 */
 
276
PDMBOTHCBDECL(int)  ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
 
277
{
 
278
    NOREF(pvUser);
 
279
    if (cb == 4)
 
280
    {
 
281
        PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
282
        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
 
283
        *pu32 = pThis->uConfigReg;
 
284
        PCI_UNLOCK(pDevIns);
 
285
        Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32));
 
286
        return VINF_SUCCESS;
 
287
    }
 
288
 
 
289
    Log(("ich9pciIOPortAddressRead: Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", Port, cb));
 
290
 
 
291
    return VERR_IOM_IOPORT_UNUSED;
 
292
}
 
293
 
 
294
static int ich9pciDataWriteAddr(PPCIGLOBALS pGlobals, PciAddress* pAddr,
 
295
                                uint32_t val, int cb, int rcReschedule)
 
296
{
 
297
    int rc = VINF_SUCCESS;
 
298
 
 
299
    if (pAddr->iRegister > 0xff)
 
300
    {
 
301
        LogRel(("PCI: attempt to write extended register: %x (%d) <- val\n", pAddr->iRegister, cb, val));
 
302
        goto out;
 
303
    }
 
304
 
 
305
    if (pAddr->iBus != 0)
 
306
    {
 
307
        if (pGlobals->aPciBus.cBridges)
 
308
        {
 
309
#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
 
310
            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pAddr->iBus);
 
311
            if (pBridgeDevice)
 
312
            {
 
313
                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
 
314
                pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, pAddr->iBus, pAddr->iDeviceFunc, pAddr->iRegister, val, cb);
 
315
            }
 
316
            else
 
317
            {
 
318
                // do nothing, bridge not found
 
319
            }
 
320
#else
 
321
            rc = rcReschedule;
 
322
            goto out;
 
323
#endif
 
324
        }
 
325
    }
 
326
    else
 
327
    {
 
328
        if (pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc])
 
329
        {
 
330
#ifdef IN_RING3
 
331
            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc];
 
332
            Log(("ich9pciConfigWrite: %s: addr=%02x val=%08x len=%d\n", aDev->name, pAddr->iRegister, val, cb));
 
333
            aDev->Int.s.pfnConfigWrite(aDev, pAddr->iRegister, val, cb);
 
334
#else
 
335
            rc = rcReschedule;
 
336
            goto out;
 
337
#endif
 
338
        }
 
339
    }
 
340
 
 
341
  out:
 
342
    Log2(("ich9pciDataWriteAddr: %02x:%02x:%02x reg %x(%d) %x %Rrc\n",
 
343
          pAddr->iBus, pAddr->iDeviceFunc >> 3, pAddr->iDeviceFunc & 0x7, pAddr->iRegister,
 
344
          cb, val, rc));
 
345
 
 
346
    return rc;
 
347
}
 
348
 
 
349
static int ich9pciDataWrite(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
 
350
{
 
351
    PciAddress aPciAddr;
 
352
 
 
353
    LogFlow(("ich9pciDataWrite: config=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
 
354
 
 
355
    if (!(pGlobals->uConfigReg & (1 << 31)))
 
356
        return VINF_SUCCESS;
 
357
 
 
358
    if ((pGlobals->uConfigReg & 0x3) != 0)
 
359
        return VINF_SUCCESS;
 
360
 
 
361
    /* Compute destination device */
 
362
    ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
 
363
 
 
364
    return ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VINF_IOM_HC_IOPORT_WRITE);
 
365
}
 
366
 
 
367
static void ich9pciNoMem(void* ptr, int cb)
 
368
{
 
369
    for (int i = 0; i < cb; i++)
 
370
        ((uint8_t*)ptr)[i] = 0xff;
 
371
}
 
372
 
 
373
/**
 
374
 * Port I/O Handler for PCI data OUT operations.
 
375
 *
 
376
 * @returns VBox status code.
 
377
 *
 
378
 * @param   pDevIns     The device instance.
 
379
 * @param   pvUser      User argument - ignored.
 
380
 * @param   uPort       Port number used for the OUT operation.
 
381
 * @param   u32         The value to output.
 
382
 * @param   cb          The value size in bytes.
 
383
 */
 
384
PDMBOTHCBDECL(int)  ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
 
385
{
 
386
    Log(("pciIOPortDataWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
 
387
    NOREF(pvUser);
 
388
    int rc = VINF_SUCCESS;
 
389
    if (!(Port % cb))
 
390
    {
 
391
        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
 
392
        rc = ich9pciDataWrite(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32, cb);
 
393
        PCI_UNLOCK(pDevIns);
 
394
    }
 
395
    else
 
396
        AssertMsgFailed(("Unaligned write to port %#x u32=%#x cb=%d\n", Port, u32, cb));
 
397
    return rc;
 
398
}
 
399
 
 
400
static int ich9pciDataReadAddr(PPCIGLOBALS pGlobals, PciAddress* pPciAddr, int cb,
 
401
                               uint32_t *pu32, int rcReschedule)
 
402
{
 
403
    int rc = VINF_SUCCESS;
 
404
 
 
405
    if (pPciAddr->iRegister > 0xff)
 
406
    {
 
407
        LogRel(("PCI: attempt to read extended register: %x\n", pPciAddr->iRegister));
 
408
        ich9pciNoMem(pu32, cb);
 
409
        goto out;
 
410
    }
 
411
 
 
412
 
 
413
    if (pPciAddr->iBus != 0)
 
414
    {
 
415
        if (pGlobals->aPciBus.cBridges)
 
416
        {
 
417
#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
 
418
            PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pPciAddr->iBus);
 
419
            if (pBridgeDevice)
 
420
            {
 
421
                AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
 
422
                *pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, pPciAddr->iBus, pPciAddr->iDeviceFunc, pPciAddr->iRegister, cb);
 
423
            }
 
424
            else
 
425
                ich9pciNoMem(pu32, cb);
 
426
#else
 
427
            rc = rcReschedule;
 
428
            goto out;
 
429
#endif
 
430
        } else
 
431
            ich9pciNoMem(pu32, cb);
 
432
    }
 
433
    else
 
434
    {
 
435
        if (pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc])
 
436
        {
 
437
#ifdef IN_RING3
 
438
            R3PTRTYPE(PCIDevice *) aDev = pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc];
 
439
            *pu32 = aDev->Int.s.pfnConfigRead(aDev, pPciAddr->iRegister, cb);
 
440
            Log(("ich9pciDataReadAddr: %s: addr=%02x val=%08x len=%d\n", aDev->name, pPciAddr->iRegister, *pu32, cb));
 
441
#else
 
442
            rc = rcReschedule;
 
443
            goto out;
 
444
#endif
 
445
        }
 
446
        else
 
447
            ich9pciNoMem(pu32, cb);
 
448
    }
 
449
 
 
450
  out:
 
451
    Log2(("ich9pciDataReadAddr: %02x:%02x:%02x reg %x(%d) gave %x %Rrc\n",
 
452
          pPciAddr->iBus, pPciAddr->iDeviceFunc >> 3, pPciAddr->iDeviceFunc & 0x7, pPciAddr->iRegister,
 
453
          cb, *pu32, rc));
 
454
 
 
455
    return rc;
 
456
}
 
457
 
 
458
static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int cb, uint32_t *pu32)
 
459
{
 
460
    PciAddress aPciAddr;
 
461
 
 
462
    LogFlow(("ich9pciDataRead: config=%x cb=%d\n",  pGlobals->uConfigReg, cb));
 
463
 
 
464
    *pu32 = 0xffffffff;
 
465
 
 
466
    if (!(pGlobals->uConfigReg & (1 << 31)))
 
467
        return VINF_SUCCESS;
 
468
 
 
469
    if ((pGlobals->uConfigReg & 0x3) != 0)
 
470
        return VINF_SUCCESS;
 
471
 
 
472
    /* Compute destination device */
 
473
    ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
 
474
 
 
475
    return ich9pciDataReadAddr(pGlobals, &aPciAddr, cb, pu32, VINF_IOM_HC_IOPORT_READ);
 
476
}
 
477
 
 
478
/**
 
479
 * Port I/O Handler for PCI data IN operations.
 
480
 *
 
481
 * @returns VBox status code.
 
482
 *
 
483
 * @param   pDevIns     The device instance.
 
484
 * @param   pvUser      User argument - ignored.
 
485
 * @param   uPort       Port number used for the IN operation.
 
486
 * @param   pu32        Where to store the result.
 
487
 * @param   cb          Number of bytes read.
 
488
 */
 
489
PDMBOTHCBDECL(int)  ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
 
490
{
 
491
    NOREF(pvUser);
 
492
    if (!(Port % cb))
 
493
    {
 
494
        PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
 
495
        int rc = ich9pciDataRead(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, cb, pu32);
 
496
        PCI_UNLOCK(pDevIns);
 
497
        Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x (%Rrc)\n", Port, cb, *pu32, rc));
 
498
        return rc;
 
499
    }
 
500
    AssertMsgFailed(("Unaligned read from port %#x cb=%d\n", Port, cb));
 
501
    return VERR_IOM_IOPORT_UNUSED;
 
502
}
 
503
 
 
504
/* Compute mapping of PCI slot and IRQ number to APIC interrupt line */
 
505
DECLINLINE(int) ich9pciSlot2ApicIrq(uint8_t uSlot, int irq_num)
 
506
{
 
507
    return (irq_num + uSlot) & 7;
 
508
}
 
509
 
 
510
/* return the global irq number corresponding to a given device irq
 
511
   pin. We could also use the bus number to have a more precise
 
512
   mapping. This is the implementation note described in the PCI spec chapter 2.2.6 */
 
513
DECLINLINE(int) ich9pciSlotGetPirq(uint8_t uBus, uint8_t uDevFn, int iIrqNum)
 
514
{
 
515
    int iSlotAddend = (uDevFn >> 3) - 1;
 
516
    return (iIrqNum + iSlotAddend) & 3;
 
517
}
 
518
 
 
519
/* irqs corresponding to PCI irqs A-D, must match pci_irq_list in rombios.c */
 
520
static const uint8_t aPciIrqs[4] = { 11, 10, 9, 5 };
 
521
 
 
522
/* Add one more level up request on APIC input line */
 
523
DECLINLINE(void) ich9pciApicLevelUp(PPCIGLOBALS pGlobals, int irq_num)
 
524
{
 
525
    ASMAtomicIncU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
 
526
}
 
527
 
 
528
/* Remove one level up request on APIC input line */
 
529
DECLINLINE(void) ich9pciApicLevelDown(PPCIGLOBALS pGlobals, int irq_num)
 
530
{
 
531
    ASMAtomicDecU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
 
532
}
 
533
 
 
534
static void ich9pciApicSetIrq(PPCIBUS pBus, uint8_t uDevFn, PCIDevice *pPciDev, int irq_num1, int iLevel, int iForcedIrq)
 
535
{
 
536
    /* This is only allowed to be called with a pointer to the root bus. */
 
537
    AssertMsg(pBus->iBus == 0, ("iBus=%u\n", pBus->iBus));
 
538
 
 
539
    if (iForcedIrq == -1)
 
540
    {
 
541
        int apic_irq, apic_level;
 
542
        PPCIGLOBALS pGlobals = PCIROOTBUS_2_PCIGLOBALS(pBus);
 
543
        int irq_num = ich9pciSlot2ApicIrq(uDevFn >> 3, irq_num1);
 
544
 
 
545
        if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH)
 
546
            ich9pciApicLevelUp(pGlobals, irq_num);
 
547
        else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW)
 
548
            ich9pciApicLevelDown(pGlobals, irq_num);
 
549
 
 
550
        apic_irq = irq_num + 0x10;
 
551
        apic_level = pGlobals->uaPciApicIrqLevels[irq_num] != 0;
 
552
        Log3(("ich9pciApicSetIrq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d\n",
 
553
              R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
 
554
        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
 
555
 
 
556
        if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
 
557
        {
 
558
            /**
 
559
             *  we raised it few lines above, as PDM_IRQ_LEVEL_FLIP_FLOP has
 
560
             * PDM_IRQ_LEVEL_HIGH bit set
 
561
             */
 
562
            ich9pciApicLevelDown(pGlobals, irq_num);
 
563
            pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
 
564
            apic_level = pGlobals->uaPciApicIrqLevels[irq_num] != 0;
 
565
            Log3(("ich9pciApicSetIrq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d (flop)\n",
 
566
                  R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num));
 
567
            pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level);
 
568
        }
 
569
    } else {
 
570
        Log3(("ich9pciApicSetIrq: (forced) %s: irq_num1=%d level=%d acpi_irq=%d\n",
 
571
              R3STRING(pPciDev->name), irq_num1, iLevel, iForcedIrq));
 
572
        pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), iForcedIrq, iLevel);
 
573
    }
 
574
}
 
575
 
 
576
static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel)
 
577
{
 
578
 
 
579
    if (PCIDevIsIntxDisabled(pPciDev))
 
580
    {
 
581
        if (MsiIsEnabled(pPciDev))
 
582
        {
 
583
            PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
 
584
            MsiNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
 
585
        }
 
586
 
 
587
        if (MsixIsEnabled(pPciDev))
 
588
        {
 
589
            PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
 
590
            MsixNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
 
591
        }
 
592
        return;
 
593
    }
 
594
 
 
595
    PPCIBUS     pBus =     &pGlobals->aPciBus;
 
596
    const bool  fIsAcpiDevice = PCIDevGetDeviceId(pPciDev) == 0x7113;
 
597
 
 
598
    /* Check if the state changed. */
 
599
    if (pPciDev->Int.s.uIrqPinState != iLevel)
 
600
    {
 
601
        pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
 
602
 
 
603
        /* Send interrupt to I/O APIC only now. */
 
604
        if (fIsAcpiDevice)
 
605
            /*
 
606
             * ACPI needs special treatment since SCI is hardwired and
 
607
             * should not be affected by PCI IRQ routing tables at the
 
608
             * same time SCI IRQ is shared in PCI sense hence this
 
609
             * kludge (i.e. we fetch the hardwired value from ACPIs
 
610
             * PCI device configuration space).
 
611
             */
 
612
            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, PCIDevGetInterruptLine(pPciDev));
 
613
        else
 
614
            ich9pciApicSetIrq(pBus, uDevFn, pPciDev, iIrq, iLevel, -1);
 
615
    }
 
616
}
 
617
 
 
618
PDMBOTHCBDECL(int)  ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
 
619
{
 
620
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
621
    PciAddress aDest;
 
622
    uint32_t u32 = 0;
 
623
 
 
624
    Log2(("ich9pciMcfgMMIOWrite: %RGp(%d) \n", GCPhysAddr, cb));
 
625
 
 
626
    PCI_LOCK(pDevIns, VINF_IOM_HC_MMIO_WRITE);
 
627
 
 
628
    ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest);
 
629
 
 
630
    switch (cb)
 
631
    {
 
632
        case 1:
 
633
            u32 = *(uint8_t*)pv;
 
634
            break;
 
635
        case 2:
 
636
            u32 = *(uint16_t*)pv;
 
637
            break;
 
638
        case 4:
 
639
            u32 = *(uint32_t*)pv;
 
640
            break;
 
641
        default:
 
642
            Assert(false);
 
643
            break;
 
644
    }
 
645
    int rc = ich9pciDataWriteAddr(pGlobals, &aDest, u32, cb, VINF_IOM_HC_MMIO_WRITE);
 
646
    PCI_UNLOCK(pDevIns);
 
647
 
 
648
    return rc;
 
649
}
 
650
 
 
651
PDMBOTHCBDECL(int)  ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
 
652
{
 
653
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
654
    PciAddress  aDest;
 
655
    uint32_t    rv;
 
656
 
 
657
    LogFlow(("ich9pciMcfgMMIORead: %RGp(%d) \n", GCPhysAddr, cb));
 
658
 
 
659
    PCI_LOCK(pDevIns, VINF_IOM_HC_MMIO_READ);
 
660
 
 
661
    ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest);
 
662
 
 
663
    int rc = ich9pciDataReadAddr(pGlobals, &aDest, cb, &rv, VINF_IOM_HC_MMIO_READ);
 
664
 
 
665
    if (RT_SUCCESS(rc))
 
666
    {
 
667
        switch (cb)
 
668
        {
 
669
            case 1:
 
670
                *(uint8_t*)pv   = (uint8_t)rv;
 
671
                break;
 
672
            case 2:
 
673
                *(uint16_t*)pv  = (uint16_t)rv;
 
674
                break;
 
675
            case 4:
 
676
                *(uint32_t*)pv  = (uint32_t)rv;
 
677
                break;
 
678
            default:
 
679
                Assert(false);
 
680
                break;
 
681
        }
 
682
    }
 
683
    PCI_UNLOCK(pDevIns);
 
684
 
 
685
    return rc;
 
686
}
 
687
 
 
688
#ifdef IN_RING3
 
689
 
 
690
DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus)
 
691
{
 
692
    /* Search for a fitting bridge. */
 
693
    for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
 
694
    {
 
695
        /*
 
696
         * Examine secondary and subordinate bus number.
 
697
         * If the target bus is in the range we pass the request on to the bridge.
 
698
         */
 
699
        PPCIDEVICE pBridgeTemp = pBus->papBridgesR3[iBridge];
 
700
        AssertMsg(pBridgeTemp && PCIIsPci2PciBridge(pBridgeTemp),
 
701
                  ("Device is not a PCI bridge but on the list of PCI bridges\n"));
 
702
 
 
703
        if (   iBus >= PCIDevGetByte(pBridgeTemp, VBOX_PCI_SECONDARY_BUS)
 
704
            && iBus <= PCIDevGetByte(pBridgeTemp, VBOX_PCI_SUBORDINATE_BUS))
 
705
            return pBridgeTemp;
 
706
    }
 
707
 
 
708
    /* Nothing found. */
 
709
    return NULL;
 
710
}
 
711
 
 
712
DECLINLINE(uint32_t) ich9pciGetRegionReg(int iRegion)
 
713
{
 
714
    return (iRegion == VBOX_PCI_ROM_SLOT) ?
 
715
            VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
 
716
}
 
717
 
 
718
#define INVALID_PCI_ADDRESS ~0U
 
719
 
 
720
static int  ich9pciUnmapRegion(PPCIDEVICE pDev, int iRegion)
 
721
{
 
722
    PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
 
723
    int rc = VINF_SUCCESS;
 
724
    PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
 
725
 
 
726
    Assert (pRegion->size != 0);
 
727
 
 
728
    if (pRegion->addr != INVALID_PCI_ADDRESS)
 
729
    {
 
730
        if (pRegion->type & PCI_ADDRESS_SPACE_IO)
 
731
        {
 
732
            /* Port IO */
 
733
            rc = PDMDevHlpIOPortDeregister(pDev->pDevIns, pRegion->addr, pRegion->size);
 
734
            AssertRC(rc);
 
735
        }
 
736
        else
 
737
        {
 
738
            RTGCPHYS GCPhysBase = pRegion->addr;
 
739
            if (pBus->pPciHlpR3->pfnIsMMIO2Base(pBus->pDevInsR3, pDev->pDevIns, GCPhysBase))
 
740
            {
 
741
                /* unmap it. */
 
742
                rc = pRegion->map_func(pDev, iRegion, NIL_RTGCPHYS, pRegion->size, (PCIADDRESSSPACE)(pRegion->type));
 
743
                AssertRC(rc);
 
744
                rc = PDMDevHlpMMIO2Unmap(pDev->pDevIns, iRegion, GCPhysBase);
 
745
            }
 
746
            else
 
747
                rc = PDMDevHlpMMIODeregister(pDev->pDevIns, GCPhysBase, pRegion->size);
 
748
        }
 
749
 
 
750
        pRegion->addr = INVALID_PCI_ADDRESS;
 
751
    }
 
752
 
 
753
    return rc;
 
754
}
 
755
 
 
756
static void ich9pciUpdateMappings(PCIDevice* pDev)
 
757
{
 
758
    PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
 
759
    uint32_t uLast, uNew;
 
760
 
 
761
    int iCmd = PCIDevGetCommand(pDev);
 
762
    for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
 
763
    {
 
764
        PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
 
765
        uint32_t uConfigReg = ich9pciGetRegionReg(iRegion);
 
766
        int32_t  iRegionSize =  pRegion->size;
 
767
        int rc;
 
768
 
 
769
        if (iRegionSize == 0)
 
770
            continue;
 
771
 
 
772
        AssertMsg((pRegion->type & PCI_ADDRESS_SPACE_BAR64) == 0, ("64-bit BARs not yet implemented\n"));
 
773
 
 
774
        if (pRegion->type & PCI_ADDRESS_SPACE_IO)
 
775
        {
 
776
            /* port IO region */
 
777
            if (iCmd & PCI_COMMAND_IOACCESS)
 
778
            {
 
779
                /* IO access allowed */
 
780
                uNew = ich9pciConfigReadDev(pDev, uConfigReg, 4);
 
781
                uNew &= ~(iRegionSize - 1);
 
782
                uLast = uNew + iRegionSize - 1;
 
783
                /* only 64K ioports on PC */
 
784
                if (uLast <= uNew || uNew == 0 || uLast >= 0x10000)
 
785
                    uNew = INVALID_PCI_ADDRESS;
 
786
            } else
 
787
                uNew = INVALID_PCI_ADDRESS;
 
788
        }
 
789
        else
 
790
        {
 
791
            /* MMIO region */
 
792
            if (iCmd & PCI_COMMAND_MEMACCESS)
 
793
            {
 
794
                uNew = ich9pciConfigReadDev(pDev, uConfigReg, 4);
 
795
                /* the ROM slot has a specific enable bit */
 
796
                if (iRegion == PCI_ROM_SLOT && !(uNew & 1))
 
797
                    uNew = INVALID_PCI_ADDRESS;
 
798
                else
 
799
                {
 
800
                    uNew &= ~(iRegionSize - 1);
 
801
                    uLast = uNew + iRegionSize - 1;
 
802
                    /* NOTE: we do not support wrapping */
 
803
                    /* XXX: as we cannot support really dynamic
 
804
                       mappings, we handle specific values as invalid
 
805
                       mappings. */
 
806
                    if (uLast <= uNew || uNew == 0 || uLast == INVALID_PCI_ADDRESS)
 
807
                        uNew = INVALID_PCI_ADDRESS;
 
808
                }
 
809
            } else
 
810
                uNew = INVALID_PCI_ADDRESS;
 
811
        }
 
812
        /* now do the real mapping */
 
813
        if (uNew != pRegion->addr)
 
814
        {
 
815
            if (pRegion->addr != INVALID_PCI_ADDRESS)
 
816
                ich9pciUnmapRegion(pDev, iRegion);
 
817
 
 
818
            pRegion->addr = uNew;
 
819
            if (pRegion->addr != INVALID_PCI_ADDRESS)
 
820
            {
 
821
                /* finally, map the region */
 
822
                rc = pRegion->map_func(pDev, iRegion,
 
823
                                       pRegion->addr, pRegion->size,
 
824
                                       (PCIADDRESSSPACE)(pRegion->type));
 
825
                AssertRC(rc);
 
826
            }
 
827
        }
 
828
    }
 
829
}
 
830
 
 
831
static DECLCALLBACK(int) ich9pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
 
832
{
 
833
    PPCIBUS     pBus = DEVINS_2_PCIBUS(pDevIns);
 
834
 
 
835
    /*
 
836
     * Check input.
 
837
     */
 
838
    if (    !pszName
 
839
        ||  !pPciDev
 
840
        ||  iDev >= (int)RT_ELEMENTS(pBus->apDevices)
 
841
        )
 
842
    {
 
843
        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
 
844
        return VERR_INVALID_PARAMETER;
 
845
    }
 
846
 
 
847
    /*
 
848
     * Register the device.
 
849
     */
 
850
    return ich9pciRegisterInternal(pBus, iDev, pPciDev, pszName);
 
851
}
 
852
 
 
853
 
 
854
static DECLCALLBACK(int) ich9pciRegisterMsi(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PPDMMSIREG pMsiReg)
 
855
{
 
856
    int rc;
 
857
 
 
858
    rc = MsiInit(pPciDev, pMsiReg);
 
859
    if (rc != VINF_SUCCESS)
 
860
        return rc;
 
861
 
 
862
    rc = MsixInit(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), pPciDev, pMsiReg);
 
863
    if (rc != VINF_SUCCESS)
 
864
        return rc;
 
865
 
 
866
    return rc;
 
867
}
 
868
 
 
869
 
 
870
static DECLCALLBACK(int) ich9pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
 
871
{
 
872
 
 
873
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
874
 
 
875
    /*
 
876
     * Check input.
 
877
     */
 
878
    if (    !pszName
 
879
        ||  !pPciDev
 
880
        ||  iDev >= (int)RT_ELEMENTS(pBus->apDevices))
 
881
    {
 
882
        AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
 
883
        return VERR_INVALID_PARAMETER;
 
884
    }
 
885
 
 
886
    /*
 
887
     * Register the device.
 
888
     */
 
889
    return ich9pciRegisterInternal(pBus, iDev, pPciDev, pszName);
 
890
}
 
891
 
 
892
static DECLCALLBACK(int) ich9pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
 
893
{
 
894
    /*
 
895
     * Validate.
 
896
     */
 
897
    AssertMsgReturn(   enmType == PCI_ADDRESS_SPACE_MEM
 
898
                    || enmType == PCI_ADDRESS_SPACE_IO
 
899
                    || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH,
 
900
                    ("Invalid enmType=%#x? Or was this a bitmask after all...\n", enmType),
 
901
                    VERR_INVALID_PARAMETER);
 
902
    AssertMsgReturn((unsigned)iRegion < PCI_NUM_REGIONS,
 
903
                    ("Invalid iRegion=%d PCI_NUM_REGIONS=%d\n", iRegion, PCI_NUM_REGIONS),
 
904
                    VERR_INVALID_PARAMETER);
 
905
    int iLastSet = ASMBitLastSetU32(cbRegion);
 
906
    AssertMsgReturn(    iLastSet != 0
 
907
                    &&  RT_BIT_32(iLastSet - 1) == cbRegion,
 
908
                    ("Invalid cbRegion=%#x iLastSet=%#x (not a power of 2 or 0)\n", cbRegion, iLastSet),
 
909
                    VERR_INVALID_PARAMETER);
 
910
 
 
911
    /*
 
912
     * Register the I/O region.
 
913
     */
 
914
    PPCIIOREGION pRegion = &pPciDev->Int.s.aIORegions[iRegion];
 
915
    pRegion->addr        = INVALID_PCI_ADDRESS;
 
916
    pRegion->size        = cbRegion;
 
917
    pRegion->type        = enmType;
 
918
    pRegion->map_func    = pfnCallback;
 
919
 
 
920
    /* Set type in the config space. */
 
921
    uint32_t u32Address = ich9pciGetRegionReg(iRegion);
 
922
    uint32_t u32Value   =   (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH ? (1 << 3) : 0)
 
923
                          | (enmType == PCI_ADDRESS_SPACE_IO ? 1 : 0);
 
924
    PCIDevSetDWord(pPciDev, u32Address, u32Value);
 
925
 
 
926
    return VINF_SUCCESS;
 
927
}
 
928
 
 
929
static DECLCALLBACK(void) ich9pciSetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
 
930
                                                    PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
 
931
{
 
932
    if (ppfnReadOld)
 
933
        *ppfnReadOld = pPciDev->Int.s.pfnConfigRead;
 
934
    pPciDev->Int.s.pfnConfigRead  = pfnRead;
 
935
 
 
936
    if (ppfnWriteOld)
 
937
        *ppfnWriteOld = pPciDev->Int.s.pfnConfigWrite;
 
938
    pPciDev->Int.s.pfnConfigWrite = pfnWrite;
 
939
}
 
940
 
 
941
/**
 
942
 * Saves a state of the PCI device.
 
943
 *
 
944
 * @returns VBox status code.
 
945
 * @param   pDevIns         Device instance of the PCI Bus.
 
946
 * @param   pPciDev         Pointer to PCI device.
 
947
 * @param   pSSM            The handle to save the state to.
 
948
 */
 
949
static DECLCALLBACK(int) ich9pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
 
950
{
 
951
    return SSMR3PutMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
 
952
}
 
953
 
 
954
static int ich9pciR3CommonSaveExec(PPCIBUS pBus, PSSMHANDLE pSSM)
 
955
{
 
956
    /*
 
957
     * Iterate thru all the devices.
 
958
     */
 
959
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
960
    {
 
961
        PPCIDEVICE pDev = pBus->apDevices[i];
 
962
        if (pDev)
 
963
        {
 
964
            /* Device position */
 
965
            SSMR3PutU32(pSSM, i);
 
966
            /* PCI config registers */
 
967
            SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config));
 
968
 
 
969
            /* Device flags */
 
970
            int rc = SSMR3PutU32(pSSM, pDev->Int.s.uFlags);
 
971
            if (RT_FAILURE(rc))
 
972
                return rc;
 
973
 
 
974
            /* IRQ pin state */
 
975
            rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
 
976
            if (RT_FAILURE(rc))
 
977
                return rc;
 
978
 
 
979
            /* MSI info */
 
980
            rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapOffset);
 
981
            if (RT_FAILURE(rc))
 
982
                return rc;
 
983
            rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapSize);
 
984
            if (RT_FAILURE(rc))
 
985
                return rc;
 
986
 
 
987
            /* MSI-X info */
 
988
            rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapOffset);
 
989
            if (RT_FAILURE(rc))
 
990
                return rc;
 
991
            rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapSize);
 
992
            if (RT_FAILURE(rc))
 
993
                return rc;
 
994
            /* Save MSI-X page state */
 
995
            if (pDev->Int.s.u8MsixCapOffset != 0)
 
996
            {
 
997
                Assert(pDev->Int.s.pMsixPageR3 != NULL);
 
998
                SSMR3PutMem(pSSM, pDev->Int.s.pMsixPageR3, 0x1000);
 
999
                if (RT_FAILURE(rc))
 
1000
                    return rc;
 
1001
            }
 
1002
        }
 
1003
    }
 
1004
    return SSMR3PutU32(pSSM, UINT32_MAX); /* terminator */
 
1005
}
 
1006
 
 
1007
static DECLCALLBACK(int) ich9pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
1008
{
 
1009
    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
1010
 
 
1011
    /*
 
1012
     * Bus state data.
 
1013
     */
 
1014
    SSMR3PutU32(pSSM, pThis->uConfigReg);
 
1015
 
 
1016
    /*
 
1017
     * Save IRQ states.
 
1018
     */
 
1019
    for (int i = 0; i < PCI_APIC_IRQ_PINS; i++)
 
1020
        SSMR3PutU32(pSSM, pThis->uaPciApicIrqLevels[i]);
 
1021
 
 
1022
    SSMR3PutU32(pSSM, ~0);        /* separator */
 
1023
 
 
1024
    return ich9pciR3CommonSaveExec(&pThis->aPciBus, pSSM);
 
1025
}
 
1026
 
 
1027
 
 
1028
static DECLCALLBACK(int) ich9pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
1029
{
 
1030
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
1031
    return ich9pciR3CommonSaveExec(pThis, pSSM);
 
1032
}
 
1033
 
 
1034
 
 
1035
static void ich9pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb)
 
1036
{
 
1037
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
1038
 
 
1039
    LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, u32Value, cb));
 
1040
 
 
1041
    /* If the current bus is not the target bus search for the bus which contains the device. */
 
1042
    if (iBus != PCIDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
 
1043
    {
 
1044
        PPCIDEVICE pBridgeDevice = ich9pciFindBridge(pBus, iBus);
 
1045
        if (pBridgeDevice)
 
1046
        {
 
1047
            AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
 
1048
            pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb);
 
1049
        }
 
1050
    }
 
1051
    else
 
1052
    {
 
1053
        /* This is the target bus, pass the write to the device. */
 
1054
        PPCIDEVICE pPciDev = pBus->apDevices[iDevice];
 
1055
        if (pPciDev)
 
1056
        {
 
1057
            Log(("%s: %s: addr=%02x val=%08x len=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb));
 
1058
            pPciDev->Int.s.pfnConfigWrite(pPciDev, u32Address, u32Value, cb);
 
1059
        }
 
1060
    }
 
1061
}
 
1062
 
 
1063
static uint32_t ich9pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb)
 
1064
{
 
1065
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
1066
    uint32_t u32Value;
 
1067
 
 
1068
    LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, cb));
 
1069
 
 
1070
    /* If the current bus is not the target bus search for the bus which contains the device. */
 
1071
    if (iBus != PCIDevGetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS))
 
1072
    {
 
1073
        PPCIDEVICE pBridgeDevice = ich9pciFindBridge(pBus, iBus);
 
1074
        if (pBridgeDevice)
 
1075
        {
 
1076
            AssertPtr( pBridgeDevice->Int.s.pfnBridgeConfigRead);
 
1077
            u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb);
 
1078
        }
 
1079
        else
 
1080
            ich9pciNoMem(&u32Value, 4);
 
1081
    }
 
1082
    else
 
1083
    {
 
1084
        /* This is the target bus, pass the read to the device. */
 
1085
        PPCIDEVICE pPciDev = pBus->apDevices[iDevice];
 
1086
        if (pPciDev)
 
1087
        {
 
1088
            u32Value = pPciDev->Int.s.pfnConfigRead(pPciDev, u32Address, cb);
 
1089
            Log(("%s: %s: u32Address=%02x u32Value=%08x cb=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb));
 
1090
        }
 
1091
        else
 
1092
            ich9pciNoMem(&u32Value, 4);
 
1093
    }
 
1094
 
 
1095
    return u32Value;
 
1096
}
 
1097
 
 
1098
 
 
1099
/**
 
1100
 * Common routine for restoring the config registers of a PCI device.
 
1101
 *
 
1102
 * @param   pDev                The PCI device.
 
1103
 * @param   pbSrcConfig         The configuration register values to be loaded.
 
1104
 * @param   fIsBridge           Whether this is a bridge device or not.
 
1105
 */
 
1106
static void pciR3CommonRestoreConfig(PPCIDEVICE pDev, uint8_t const *pbSrcConfig, bool fIsBridge)
 
1107
{
 
1108
    /*
 
1109
     * This table defines the fields for normal devices and bridge devices, and
 
1110
     * the order in which they need to be restored.
 
1111
     */
 
1112
    static const struct PciField
 
1113
    {
 
1114
        uint8_t     off;
 
1115
        uint8_t     cb;
 
1116
        uint8_t     fWritable;
 
1117
        uint8_t     fBridge;
 
1118
        const char *pszName;
 
1119
    } s_aFields[] =
 
1120
    {
 
1121
        /* off,cb,fW,fB, pszName */
 
1122
        { VBOX_PCI_VENDOR_ID, 2, 0, 3, "VENDOR_ID" },
 
1123
        { VBOX_PCI_DEVICE_ID, 2, 0, 3, "DEVICE_ID" },
 
1124
        { VBOX_PCI_STATUS, 2, 1, 3, "STATUS" },
 
1125
        { VBOX_PCI_REVISION_ID, 1, 0, 3, "REVISION_ID" },
 
1126
        { VBOX_PCI_CLASS_PROG, 1, 0, 3, "CLASS_PROG" },
 
1127
        { VBOX_PCI_CLASS_SUB, 1, 0, 3, "CLASS_SUB" },
 
1128
        { VBOX_PCI_CLASS_BASE, 1, 0, 3, "CLASS_BASE" },
 
1129
        { VBOX_PCI_CACHE_LINE_SIZE, 1, 1, 3, "CACHE_LINE_SIZE" },
 
1130
        { VBOX_PCI_LATENCY_TIMER, 1, 1, 3, "LATENCY_TIMER" },
 
1131
        { VBOX_PCI_HEADER_TYPE, 1, 0, 3, "HEADER_TYPE" },
 
1132
        { VBOX_PCI_BIST, 1, 1, 3, "BIST" },
 
1133
        { VBOX_PCI_BASE_ADDRESS_0, 4, 1, 3, "BASE_ADDRESS_0" },
 
1134
        { VBOX_PCI_BASE_ADDRESS_1, 4, 1, 3, "BASE_ADDRESS_1" },
 
1135
        { VBOX_PCI_BASE_ADDRESS_2, 4, 1, 1, "BASE_ADDRESS_2" },
 
1136
        { VBOX_PCI_PRIMARY_BUS, 1, 1, 2, "PRIMARY_BUS" },       // fWritable = ??
 
1137
        { VBOX_PCI_SECONDARY_BUS, 1, 1, 2, "SECONDARY_BUS" },     // fWritable = ??
 
1138
        { VBOX_PCI_SUBORDINATE_BUS, 1, 1, 2, "SUBORDINATE_BUS" },   // fWritable = ??
 
1139
        { VBOX_PCI_SEC_LATENCY_TIMER, 1, 1, 2, "SEC_LATENCY_TIMER" }, // fWritable = ??
 
1140
        { VBOX_PCI_BASE_ADDRESS_3, 4, 1, 1, "BASE_ADDRESS_3" },
 
1141
        { VBOX_PCI_IO_BASE, 1, 1, 2, "IO_BASE" },           // fWritable = ??
 
1142
        { VBOX_PCI_IO_LIMIT, 1, 1, 2, "IO_LIMIT" },          // fWritable = ??
 
1143
        { VBOX_PCI_SEC_STATUS, 2, 1, 2, "SEC_STATUS" },        // fWritable = ??
 
1144
        { VBOX_PCI_BASE_ADDRESS_4, 4, 1, 1, "BASE_ADDRESS_4" },
 
1145
        { VBOX_PCI_MEMORY_BASE, 2, 1, 2, "MEMORY_BASE" },       // fWritable = ??
 
1146
        { VBOX_PCI_MEMORY_LIMIT, 2, 1, 2, "MEMORY_LIMIT" },      // fWritable = ??
 
1147
        { VBOX_PCI_BASE_ADDRESS_5, 4, 1, 1, "BASE_ADDRESS_5" },
 
1148
        { VBOX_PCI_PREF_MEMORY_BASE, 2, 1, 2, "PREF_MEMORY_BASE" },  // fWritable = ??
 
1149
        { VBOX_PCI_PREF_MEMORY_LIMIT, 2, 1, 2, "PREF_MEMORY_LIMIT" }, // fWritable = ??
 
1150
        { VBOX_PCI_CARDBUS_CIS, 4, 1, 1, "CARDBUS_CIS" },       // fWritable = ??
 
1151
        { VBOX_PCI_PREF_BASE_UPPER32, 4, 1, 2, "PREF_BASE_UPPER32" }, // fWritable = ??
 
1152
        { VBOX_PCI_SUBSYSTEM_VENDOR_ID, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },// fWritable = !?
 
1153
        { VBOX_PCI_PREF_LIMIT_UPPER32, 4, 1, 2, "PREF_LIMIT_UPPER32" },// fWritable = ??
 
1154
        { VBOX_PCI_SUBSYSTEM_ID, 2, 0, 1, "SUBSYSTEM_ID" },      // fWritable = !?
 
1155
        { VBOX_PCI_ROM_ADDRESS, 4, 1, 1, "ROM_ADDRESS" },       // fWritable = ?!
 
1156
        { VBOX_PCI_IO_BASE_UPPER16, 2, 1, 2, "IO_BASE_UPPER16" },   // fWritable = ?!
 
1157
        { VBOX_PCI_IO_LIMIT_UPPER16, 2, 1, 2, "IO_LIMIT_UPPER16" },  // fWritable = ?!
 
1158
        { VBOX_PCI_CAPABILITY_LIST, 4, 0, 3, "CAPABILITY_LIST" },   // fWritable = !? cb=!?
 
1159
        { VBOX_PCI_RESERVED_38, 4, 1, 1, "RESERVED_38" },               // ???
 
1160
        { VBOX_PCI_ROM_ADDRESS_BR, 4, 1, 2, "ROM_ADDRESS_BR" },    // fWritable = !? cb=!? fBridge=!?
 
1161
        { VBOX_PCI_INTERRUPT_LINE, 1, 1, 3, "INTERRUPT_LINE" },    // fBridge=??
 
1162
        { VBOX_PCI_INTERRUPT_PIN, 1, 0, 3, "INTERRUPT_PIN" },     // fBridge=??
 
1163
        { VBOX_PCI_MIN_GNT, 1, 0, 1, "MIN_GNT" },
 
1164
        { VBOX_PCI_BRIDGE_CONTROL, 2, 1, 2, "BRIDGE_CONTROL" },    // fWritable = !?
 
1165
        { VBOX_PCI_MAX_LAT, 1, 0, 1, "MAX_LAT" },
 
1166
        /* The COMMAND register must come last as it requires the *ADDRESS*
 
1167
           registers to be restored before we pretent to change it from 0 to
 
1168
           whatever value the guest assigned it. */
 
1169
        { VBOX_PCI_COMMAND, 2, 1, 3, "COMMAND" },
 
1170
    };
 
1171
 
 
1172
#ifdef RT_STRICT
 
1173
    /* Check that we've got full register coverage. */
 
1174
    uint32_t bmDevice[0x40 / 32];
 
1175
    uint32_t bmBridge[0x40 / 32];
 
1176
    RT_ZERO(bmDevice);
 
1177
    RT_ZERO(bmBridge);
 
1178
    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
 
1179
    {
 
1180
        uint8_t off = s_aFields[i].off;
 
1181
        uint8_t cb  = s_aFields[i].cb;
 
1182
        uint8_t f   = s_aFields[i].fBridge;
 
1183
        while (cb-- > 0)
 
1184
        {
 
1185
            if (f & 1) AssertMsg(!ASMBitTest(bmDevice, off), ("%#x\n", off));
 
1186
            if (f & 2) AssertMsg(!ASMBitTest(bmBridge, off), ("%#x\n", off));
 
1187
            if (f & 1) ASMBitSet(bmDevice, off);
 
1188
            if (f & 2) ASMBitSet(bmBridge, off);
 
1189
            off++;
 
1190
        }
 
1191
    }
 
1192
    for (uint32_t off = 0; off < 0x40; off++)
 
1193
    {
 
1194
        AssertMsg(ASMBitTest(bmDevice, off), ("%#x\n", off));
 
1195
        AssertMsg(ASMBitTest(bmBridge, off), ("%#x\n", off));
 
1196
    }
 
1197
#endif
 
1198
 
 
1199
    /*
 
1200
     * Loop thru the fields covering the 64 bytes of standard registers.
 
1201
     */
 
1202
    uint8_t const fBridge = fIsBridge ? 2 : 1;
 
1203
    uint8_t *pbDstConfig = &pDev->config[0];
 
1204
    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
 
1205
        if (s_aFields[i].fBridge & fBridge)
 
1206
        {
 
1207
            uint8_t const   off = s_aFields[i].off;
 
1208
            uint8_t const   cb  = s_aFields[i].cb;
 
1209
            uint32_t        u32Src;
 
1210
            uint32_t        u32Dst;
 
1211
            switch (cb)
 
1212
            {
 
1213
                case 1:
 
1214
                    u32Src = pbSrcConfig[off];
 
1215
                    u32Dst = pbDstConfig[off];
 
1216
                    break;
 
1217
                case 2:
 
1218
                    u32Src = *(uint16_t const *)&pbSrcConfig[off];
 
1219
                    u32Dst = *(uint16_t const *)&pbDstConfig[off];
 
1220
                    break;
 
1221
                case 4:
 
1222
                    u32Src = *(uint32_t const *)&pbSrcConfig[off];
 
1223
                    u32Dst = *(uint32_t const *)&pbDstConfig[off];
 
1224
                    break;
 
1225
                default:
 
1226
                    AssertFailed();
 
1227
                    continue;
 
1228
            }
 
1229
 
 
1230
            if (    u32Src != u32Dst
 
1231
                ||  off == VBOX_PCI_COMMAND)
 
1232
            {
 
1233
                if (u32Src != u32Dst)
 
1234
                {
 
1235
                    if (!s_aFields[i].fWritable)
 
1236
                        LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x - !READ ONLY!\n",
 
1237
                                pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
 
1238
                    else
 
1239
                        LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x\n",
 
1240
                                pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
 
1241
                }
 
1242
                if (off == VBOX_PCI_COMMAND)
 
1243
                    PCIDevSetCommand(pDev, 0); /* For remapping, see ich9pciR3CommonLoadExec. */
 
1244
                pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb);
 
1245
            }
 
1246
        }
 
1247
 
 
1248
    /*
 
1249
     * The device dependent registers.
 
1250
     *
 
1251
     * We will not use ConfigWrite here as we have no clue about the size
 
1252
     * of the registers, so the device is responsible for correctly
 
1253
     * restoring functionality governed by these registers.
 
1254
     */
 
1255
    for (uint32_t off = 0x40; off < sizeof(pDev->config); off++)
 
1256
        if (pbDstConfig[off] != pbSrcConfig[off])
 
1257
        {
 
1258
            LogRel(("PCI: %8s/%u: register %02x: %02x -> %02x\n",
 
1259
                    pDev->name, pDev->pDevIns->iInstance, off, pbDstConfig[off], pbSrcConfig[off])); /** @todo make this Log() later. */
 
1260
            pbDstConfig[off] = pbSrcConfig[off];
 
1261
        }
 
1262
}
 
1263
 
 
1264
/**
 
1265
 * Common worker for ich9pciR3LoadExec and ich9pcibridgeR3LoadExec.
 
1266
 *
 
1267
 * @returns VBox status code.
 
1268
 * @param   pBus                The bus which data is being loaded.
 
1269
 * @param   pSSM                The saved state handle.
 
1270
 * @param   uVersion            The data version.
 
1271
 * @param   uPass               The pass.
 
1272
 */
 
1273
static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
1274
{
 
1275
    uint32_t    u32;
 
1276
    uint32_t    i;
 
1277
    int         rc;
 
1278
 
 
1279
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
 
1280
 
 
1281
    /*
 
1282
     * Iterate thru all the devices and write 0 to the COMMAND register so
 
1283
     * that all the memory is unmapped before we start restoring the saved
 
1284
     * mapping locations.
 
1285
     *
 
1286
     * The register value is restored afterwards so we can do proper
 
1287
     * LogRels in pciR3CommonRestoreConfig.
 
1288
     */
 
1289
    for (i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
1290
    {
 
1291
        PPCIDEVICE pDev = pBus->apDevices[i];
 
1292
        if (pDev)
 
1293
        {
 
1294
            uint16_t u16 = PCIDevGetCommand(pDev);
 
1295
            pDev->Int.s.pfnConfigWrite(pDev, VBOX_PCI_COMMAND, 0, 2);
 
1296
            PCIDevSetCommand(pDev, u16);
 
1297
            Assert(PCIDevGetCommand(pDev) == u16);
 
1298
        }
 
1299
    }
 
1300
 
 
1301
    void* pvMsixPage = RTMemTmpAllocZ(0x1000);
 
1302
    /*
 
1303
     * Iterate all the devices.
 
1304
     */
 
1305
    for (i = 0;; i++)
 
1306
    {
 
1307
        PPCIDEVICE  pDev;
 
1308
        PCIDEVICE   DevTmp;
 
1309
 
 
1310
        /* index / terminator */
 
1311
        rc = SSMR3GetU32(pSSM, &u32);
 
1312
        if (RT_FAILURE(rc))
 
1313
            return rc;
 
1314
        if (u32 == (uint32_t)~0)
 
1315
            break;
 
1316
        if (    u32 >= RT_ELEMENTS(pBus->apDevices)
 
1317
            ||  u32 < i)
 
1318
        {
 
1319
            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
 
1320
            goto out;
 
1321
        }
 
1322
 
 
1323
        /* skip forward to the device checking that no new devices are present. */
 
1324
        for (; i < u32; i++)
 
1325
        {
 
1326
            pDev = pBus->apDevices[i];
 
1327
            if (pDev)
 
1328
            {
 
1329
                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pDev->name,
 
1330
                        PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev)));
 
1331
                if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
 
1332
                    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"),
 
1333
                                            i, pDev->name, PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev));
 
1334
            }
 
1335
        }
 
1336
 
 
1337
        /* get the data */
 
1338
        DevTmp.Int.s.uFlags = 0;
 
1339
        DevTmp.Int.s.u8MsiCapOffset = 0;
 
1340
        DevTmp.Int.s.u8MsiCapSize = 0;
 
1341
        DevTmp.Int.s.u8MsixCapOffset = 0;
 
1342
        DevTmp.Int.s.u8MsixCapSize = 0;
 
1343
        DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
 
1344
        SSMR3GetMem(pSSM, DevTmp.config, sizeof(DevTmp.config));
 
1345
 
 
1346
        rc = SSMR3GetU32(pSSM, &DevTmp.Int.s.uFlags);
 
1347
        if (RT_FAILURE(rc))
 
1348
            goto out;
 
1349
 
 
1350
        rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
 
1351
        if (RT_FAILURE(rc))
 
1352
            goto out;
 
1353
 
 
1354
        rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapOffset);
 
1355
        if (RT_FAILURE(rc))
 
1356
            goto out;
 
1357
 
 
1358
        rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapSize);
 
1359
        if (RT_FAILURE(rc))
 
1360
            goto out;
 
1361
 
 
1362
        rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapOffset);
 
1363
        if (RT_FAILURE(rc))
 
1364
            goto out;
 
1365
 
 
1366
        rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapSize);
 
1367
        if (RT_FAILURE(rc))
 
1368
            goto out;
 
1369
 
 
1370
        /* Load MSI-X page state */
 
1371
        if (DevTmp.Int.s.u8MsixCapOffset != 0)
 
1372
        {
 
1373
            Assert(pvMsixPage != NULL);
 
1374
            SSMR3GetMem(pSSM, pvMsixPage, 0x1000);
 
1375
            if (RT_FAILURE(rc))
 
1376
                goto out;
 
1377
        }
 
1378
 
 
1379
        /* check that it's still around. */
 
1380
        pDev = pBus->apDevices[i];
 
1381
        if (!pDev)
 
1382
        {
 
1383
            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
 
1384
                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
 
1385
            if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
 
1386
                return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"),
 
1387
                                        i, PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp));
 
1388
            continue;
 
1389
        }
 
1390
 
 
1391
        /* match the vendor id assuming that this will never be changed. */
 
1392
        if (    PCIDevGetVendorId(&DevTmp) != PCIDevGetVendorId(pDev))
 
1393
            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
 
1394
                                     i, pDev->name, PCIDevGetVendorId(&DevTmp), PCIDevGetVendorId(pDev));
 
1395
 
 
1396
        /* commit the loaded device config. */
 
1397
        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
 
1398
 
 
1399
        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
 
1400
        pDev->Int.s.u8MsiCapOffset  = DevTmp.Int.s.u8MsiCapOffset;
 
1401
        pDev->Int.s.u8MsiCapSize    = DevTmp.Int.s.u8MsiCapSize;
 
1402
        pDev->Int.s.u8MsixCapOffset = DevTmp.Int.s.u8MsixCapOffset;
 
1403
        pDev->Int.s.u8MsixCapSize   = DevTmp.Int.s.u8MsixCapSize;
 
1404
        if (DevTmp.Int.s.u8MsixCapSize != 0)
 
1405
        {
 
1406
            Assert(pDev->Int.s.pMsixPageR3 != NULL);
 
1407
            memcpy(pDev->Int.s.pMsixPageR3, pvMsixPage, 0x1000);
 
1408
        }
 
1409
    }
 
1410
 
 
1411
  out:
 
1412
    if (pvMsixPage)
 
1413
        RTMemTmpFree(pvMsixPage);
 
1414
 
 
1415
    return rc;
 
1416
}
 
1417
 
 
1418
/**
 
1419
 * Loads a saved PCI device state.
 
1420
 *
 
1421
 * @returns VBox status code.
 
1422
 * @param   pDevIns         Device instance of the PCI Bus.
 
1423
 * @param   pPciDev         Pointer to PCI device.
 
1424
 * @param   pSSM            The handle to the saved state.
 
1425
 */
 
1426
static DECLCALLBACK(int) ich9pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
 
1427
{
 
1428
    return SSMR3GetMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
 
1429
}
 
1430
 
 
1431
static DECLCALLBACK(int) ich9pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
1432
{
 
1433
    PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
1434
    PPCIBUS     pBus  = &pThis->aPciBus;
 
1435
    uint32_t    u32;
 
1436
    int         rc;
 
1437
 
 
1438
    /* We ignore this version as there's no saved state with it anyway */
 
1439
    if (uVersion == VBOX_ICH9PCI_SAVED_STATE_VERSION_NOMSI)
 
1440
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
1441
    if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI)
 
1442
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
1443
 
 
1444
    /*
 
1445
     * Bus state data.
 
1446
     */
 
1447
    SSMR3GetU32(pSSM, &pThis->uConfigReg);
 
1448
 
 
1449
    /*
 
1450
     * Load IRQ states.
 
1451
     */
 
1452
    for (int i = 0; i < PCI_APIC_IRQ_PINS; i++)
 
1453
        SSMR3GetU32(pSSM, (uint32_t*)&pThis->uaPciApicIrqLevels[i]);
 
1454
 
 
1455
    /* separator */
 
1456
    rc = SSMR3GetU32(pSSM, &u32);
 
1457
    if (RT_FAILURE(rc))
 
1458
        return rc;
 
1459
    if (u32 != (uint32_t)~0)
 
1460
        AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
 
1461
 
 
1462
    return ich9pciR3CommonLoadExec(pBus, pSSM, uVersion, uPass);
 
1463
}
 
1464
 
 
1465
static DECLCALLBACK(int) ich9pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
1466
{
 
1467
    PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
1468
    if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION_MSI)
 
1469
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
 
1470
    return ich9pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
 
1471
}
 
1472
 
 
1473
static uint32_t ich9pciConfigRead(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t len)
 
1474
{
 
1475
    /* Will only work in LSB case */
 
1476
    uint32_t   u32Val;
 
1477
    PciAddress aPciAddr;
 
1478
 
 
1479
    aPciAddr.iBus = uBus;
 
1480
    aPciAddr.iDeviceFunc = uDevFn;
 
1481
    aPciAddr.iRegister = addr;
 
1482
 
 
1483
    /* cannot be rescheduled, as already in R3 */
 
1484
    int rc = ich9pciDataReadAddr(pGlobals, &aPciAddr, len, &u32Val, VERR_INTERNAL_ERROR);
 
1485
    AssertRC(rc);
 
1486
    return u32Val;
 
1487
}
 
1488
 
 
1489
static void ich9pciConfigWrite(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val, uint32_t len)
 
1490
{
 
1491
    PciAddress aPciAddr;
 
1492
 
 
1493
    aPciAddr.iBus = uBus;
 
1494
    aPciAddr.iDeviceFunc = uDevFn;
 
1495
    aPciAddr.iRegister = addr;
 
1496
 
 
1497
    /* cannot be rescheduled, as already in R3 */
 
1498
    int rc = ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VERR_INTERNAL_ERROR);
 
1499
    AssertRC(rc);
 
1500
}
 
1501
 
 
1502
static void ich9pciSetRegionAddress(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, int iRegion, uint32_t addr)
 
1503
{
 
1504
    uint32_t uReg = ich9pciGetRegionReg(iRegion);
 
1505
 
 
1506
    /* Read memory type first. */
 
1507
    uint8_t uResourceType = ich9pciConfigRead(pGlobals, uBus, uDevFn, uReg, 1);
 
1508
    /* Read command register. */
 
1509
    uint16_t uCmd = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, 2);
 
1510
 
 
1511
    if ( iRegion == PCI_ROM_SLOT )
 
1512
        uCmd |= PCI_COMMAND_MEMACCESS;
 
1513
    else if ((uResourceType & PCI_ADDRESS_SPACE_IO) == PCI_ADDRESS_SPACE_IO)
 
1514
        uCmd |= PCI_COMMAND_IOACCESS; /* Enable I/O space access. */
 
1515
    else /* The region is MMIO. */
 
1516
        uCmd |= PCI_COMMAND_MEMACCESS; /* Enable MMIO access. */
 
1517
 
 
1518
    /* Write address of the device. */
 
1519
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, uReg, addr, 4);
 
1520
 
 
1521
    /* enable memory mappings */
 
1522
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, uCmd, 2);
 
1523
}
 
1524
 
 
1525
 
 
1526
static void ich9pciBiosInitBridge(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
 
1527
{
 
1528
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_SECONDARY_BUS, pGlobals->uBus, 1);
 
1529
    /* Temporary until we know how many other bridges are behind this one. */
 
1530
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, 0xff, 1);
 
1531
 
 
1532
    /* Add position of this bridge into the array. */
 
1533
    paBridgePositions[cBridgeDepth+1] = (uDevFn >> 3);
 
1534
 
 
1535
    /*
 
1536
     * The I/O range for the bridge must be aligned to a 4KB boundary.
 
1537
     * This does not change anything really as the access to the device is not going
 
1538
     * through the bridge but we want to be compliant to the spec.
 
1539
     */
 
1540
    if ((pGlobals->uPciBiosIo % 4096) != 0)
 
1541
    {
 
1542
        pGlobals->uPciBiosIo = RT_ALIGN_32(pGlobals->uPciBiosIo, 4*1024);
 
1543
        Log(("%s: Aligned I/O start address. New address %#x\n", __FUNCTION__, pGlobals->uPciBiosIo));
 
1544
    }
 
1545
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_BASE, (pGlobals->uPciBiosIo >> 8) & 0xf0, 1);
 
1546
 
 
1547
    /* The MMIO range for the bridge must be aligned to a 1MB boundary. */
 
1548
    if ((pGlobals->uPciBiosMmio % (1024 * 1024)) != 0)
 
1549
    {
 
1550
        pGlobals->uPciBiosMmio = RT_ALIGN_32(pGlobals->uPciBiosMmio, 1024*1024);
 
1551
        Log(("%s: Aligned MMIO start address. New address %#x\n", __FUNCTION__, pGlobals->uPciBiosMmio));
 
1552
    }
 
1553
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_BASE, (pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xffff0), 2);
 
1554
 
 
1555
    /* Save values to compare later to. */
 
1556
    uint32_t u32IoAddressBase = pGlobals->uPciBiosIo;
 
1557
    uint32_t u32MMIOAddressBase = pGlobals->uPciBiosMmio;
 
1558
 
 
1559
    /* Init devices behind the bridge and possibly other bridges as well. */
 
1560
    for (int iDev = 0; iDev <= 255; iDev++)
 
1561
        ich9pciBiosInitDevice(pGlobals, uBus + 1, iDev, cBridgeDepth + 1, paBridgePositions);
 
1562
 
 
1563
    /* The number of bridges behind the this one is now available. */
 
1564
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, pGlobals->uBus, 1);
 
1565
 
 
1566
    /*
 
1567
     * Set I/O limit register. If there is no device with I/O space behind the bridge
 
1568
     * we set a lower value than in the base register.
 
1569
     * The result with a real bridge is that no I/O transactions are passed to the secondary
 
1570
     * interface. Again this doesn't really matter here but we want to be compliant to the spec.
 
1571
     */
 
1572
    if ((u32IoAddressBase != pGlobals->uPciBiosIo) && ((pGlobals->uPciBiosIo % 4096) != 0))
 
1573
    {
 
1574
        /* The upper boundary must be one byte less than a 4KB boundary. */
 
1575
        pGlobals->uPciBiosIo = RT_ALIGN_32(pGlobals->uPciBiosIo, 4*1024);
 
1576
    }
 
1577
 
 
1578
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->uPciBiosIo >> 8) & 0xf0) - 1, 1);
 
1579
 
 
1580
    /* Same with the MMIO limit register but with 1MB boundary here. */
 
1581
    if ((u32MMIOAddressBase != pGlobals->uPciBiosMmio) && ((pGlobals->uPciBiosMmio % (1024 * 1024)) != 0))
 
1582
    {
 
1583
        /* The upper boundary must be one byte less than a 1MB boundary. */
 
1584
        pGlobals->uPciBiosMmio = RT_ALIGN_32(pGlobals->uPciBiosMmio, 1024*1024);
 
1585
    }
 
1586
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xfff0)) - 1, 2);
 
1587
 
 
1588
    /*
 
1589
     * Set the prefetch base and limit registers. We currently have no device with a prefetchable region
 
1590
     * which may be behind a bridge. That's why it is unconditionally disabled here atm by writing a higher value into
 
1591
     * the base register than in the limit register.
 
1592
     */
 
1593
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_BASE, 0xfff0, 2);
 
1594
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_LIMIT, 0x0, 2);
 
1595
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, 0x00, 4);
 
1596
    ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, 0x00, 4);
 
1597
}
 
1598
 
 
1599
static void ich9pciBiosInitDevice(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
 
1600
{
 
1601
    uint32_t *paddr;
 
1602
    uint16_t uDevClass, uVendor, uDevice;
 
1603
    uint8_t uCmd;
 
1604
 
 
1605
    uDevClass  = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
 
1606
    uVendor    = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
 
1607
    uDevice    = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_DEVICE_ID, 2);
 
1608
 
 
1609
    /* If device is present */
 
1610
    if (uVendor == 0xffff)
 
1611
        return;
 
1612
 
 
1613
    switch (uDevClass)
 
1614
    {
 
1615
        case 0x0101:
 
1616
            /* IDE controller */
 
1617
            ich9pciConfigWrite(pGlobals, uBus, uDevFn, 0x40, 0x8000, 2); /* enable IDE0 */
 
1618
            ich9pciConfigWrite(pGlobals, uBus, uDevFn, 0x42, 0x8000, 2); /* enable IDE1 */
 
1619
            goto default_map;
 
1620
            break;
 
1621
        case 0x0300:
 
1622
            /* VGA controller */
 
1623
            if (uVendor != 0x80ee)
 
1624
                goto default_map;
 
1625
            /* VGA: map frame buffer to default Bochs VBE address */
 
1626
            ich9pciSetRegionAddress(pGlobals, uBus, uDevFn, 0, 0xE0000000);
 
1627
            /*
 
1628
             * Legacy VGA I/O ports are implicitly decoded by a VGA class device. But
 
1629
             * only the framebuffer (i.e., a memory region) is explicitly registered via
 
1630
             * ich9pciSetRegionAddress, so I/O decoding must be enabled manually.
 
1631
             */
 
1632
            uCmd = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, 1);
 
1633
            ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND,
 
1634
                               /* Enable I/O space access. */
 
1635
                               uCmd | PCI_COMMAND_IOACCESS,
 
1636
                               1);
 
1637
            break;
 
1638
       case 0x0604:
 
1639
            /* PCI-to-PCI bridge. */
 
1640
            ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PRIMARY_BUS, uBus, 1);
 
1641
 
 
1642
            AssertMsg(pGlobals->uBus < 255, ("Too many bridges on the bus\n"));
 
1643
            pGlobals->uBus++;
 
1644
            ich9pciBiosInitBridge(pGlobals, uBus, uDevFn, cBridgeDepth, paBridgePositions);
 
1645
            break;
 
1646
        default:
 
1647
        default_map:
 
1648
        {
 
1649
            /* default memory mappings */
 
1650
            /*
 
1651
             * We ignore ROM region here.
 
1652
             */
 
1653
            for (int iRegion = 0; iRegion < (PCI_NUM_REGIONS-1); iRegion++)
 
1654
            {
 
1655
                uint32_t u32Address = ich9pciGetRegionReg(iRegion);
 
1656
 
 
1657
                /* Calculate size - we write all 1s into the BAR, and then evaluate which bits
 
1658
                   are cleared. . */
 
1659
                uint8_t u8ResourceType = ich9pciConfigRead(pGlobals, uBus, uDevFn, u32Address, 1);
 
1660
                ich9pciConfigWrite(pGlobals, uBus, uDevFn, u32Address, UINT32_C(0xffffffff), 4);
 
1661
                uint32_t u32Size = ich9pciConfigRead(pGlobals, uBus, uDevFn, u32Address, 4);
 
1662
                /* Clear resource information depending on resource type. */
 
1663
                if ((u8ResourceType & PCI_COMMAND_IOACCESS) == PCI_COMMAND_IOACCESS) /* I/O */
 
1664
                    u32Size &= ~(0x01);
 
1665
                else                        /* MMIO */
 
1666
                    u32Size &= ~(0x0f);
 
1667
 
 
1668
                bool fIsPio = ((u8ResourceType & PCI_COMMAND_IOACCESS) == PCI_COMMAND_IOACCESS);
 
1669
                /*
 
1670
                 * Invert all bits and add 1 to get size of the region.
 
1671
                 * (From PCI implementation note)
 
1672
                 */
 
1673
                if (fIsPio && (u32Size & UINT32_C(0xffff0000)) == 0)
 
1674
                    u32Size = (~(u32Size | UINT32_C(0xffff0000))) + 1;
 
1675
                else
 
1676
                    u32Size = (~u32Size) + 1;
 
1677
 
 
1678
                Log(("%s: Size of region %u for device %d on bus %d is %u\n", __FUNCTION__, iRegion, uDevFn, uBus, u32Size));
 
1679
 
 
1680
                if (u32Size)
 
1681
                {
 
1682
                    paddr = fIsPio ? &pGlobals->uPciBiosIo : &pGlobals->uPciBiosMmio;
 
1683
                    *paddr = (*paddr + u32Size - 1) & ~(u32Size - 1);
 
1684
                    Log(("%s: Start address of %s region %u is %#x\n", __FUNCTION__, (fIsPio ? "I/O" : "MMIO"), iRegion, *paddr));
 
1685
                    ich9pciSetRegionAddress(pGlobals, uBus, uDevFn, iRegion, *paddr);
 
1686
                    *paddr += u32Size;
 
1687
                    Log(("%s: New address is %#x\n", __FUNCTION__, *paddr));
 
1688
                }
 
1689
            }
 
1690
            break;
 
1691
        }
 
1692
    }
 
1693
 
 
1694
    /* map the interrupt */
 
1695
    uint32_t iPin = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_INTERRUPT_PIN, 1);
 
1696
    if (iPin != 0)
 
1697
    {
 
1698
        uint8_t uBridgeDevFn = uDevFn;
 
1699
        iPin--;
 
1700
 
 
1701
        /* We need to go up to the host bus to see which irq this device will assert there. */
 
1702
        while (cBridgeDepth != 0)
 
1703
        {
 
1704
            /* Get the pin the device would assert on the bridge. */
 
1705
            iPin = ((uBridgeDevFn >> 3) + iPin) & 3;
 
1706
            uBridgeDevFn = paBridgePositions[cBridgeDepth];
 
1707
            cBridgeDepth--;
 
1708
        }
 
1709
 
 
1710
        int iIrq = aPciIrqs[ich9pciSlotGetPirq(uBus, uDevFn, iPin)];
 
1711
        ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_INTERRUPT_LINE, iIrq, 1);
 
1712
    }
 
1713
}
 
1714
 
 
1715
static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
 
1716
{
 
1717
    unsigned    i;
 
1718
    uint8_t     elcr[2] = {0, 0};
 
1719
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
1720
    PVM         pVM = PDMDevHlpGetVM(pDevIns);
 
1721
    Assert(pVM);
 
1722
 
 
1723
    /*
 
1724
     * Set the start addresses.
 
1725
     */
 
1726
    pGlobals->uPciBiosIo  = 0xd000;
 
1727
    pGlobals->uPciBiosMmio = UINT32_C(0xf0000000);
 
1728
    pGlobals->uBus = 0;
 
1729
 
 
1730
    /*
 
1731
     * Init the devices.
 
1732
     */
 
1733
    for (i = 0; i < 256; i++)
 
1734
    {
 
1735
        uint8_t aBridgePositions[256];
 
1736
 
 
1737
        memset(aBridgePositions, 0, sizeof(aBridgePositions));
 
1738
        Log2(("PCI: Initializing device %d (%#x)\n",
 
1739
              i, 0x80000000 | (i << 8)));
 
1740
        ich9pciBiosInitDevice(pGlobals, 0, i, 0, aBridgePositions);
 
1741
    }
 
1742
 
 
1743
    return VINF_SUCCESS;
 
1744
}
 
1745
 
 
1746
static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PCIDevice *aDev, uint32_t u32Address, unsigned len)
 
1747
{
 
1748
    if ((u32Address + len) > 256 && (u32Address + len) < 4096)
 
1749
    {
 
1750
        AssertMsgReturn(false, ("Read from extended registers falled back to generic code\n"), 0);
 
1751
    }
 
1752
 
 
1753
    if (   PCIIsMsiCapable(aDev)
 
1754
        && (u32Address >= aDev->Int.s.u8MsiCapOffset)
 
1755
        && (u32Address <  aDev->Int.s.u8MsiCapOffset + aDev->Int.s.u8MsiCapSize)
 
1756
       )
 
1757
    {
 
1758
        return MsiPciConfigRead(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), aDev, u32Address, len);
 
1759
    }
 
1760
 
 
1761
    if (   PCIIsMsixCapable(aDev)
 
1762
        && (u32Address >= aDev->Int.s.u8MsixCapOffset)
 
1763
        && (u32Address <  aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
 
1764
       )
 
1765
    {
 
1766
        return MsixPciConfigRead(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), aDev, u32Address, len);
 
1767
    }
 
1768
 
 
1769
    AssertMsgReturn(u32Address + len <= 256, ("Read after end of PCI config space\n"),
 
1770
                    0);
 
1771
    switch (len)
 
1772
    {
 
1773
        case 1:
 
1774
            return PCIDevGetByte(aDev,  u32Address);
 
1775
        case 2:
 
1776
            return PCIDevGetWord(aDev,  u32Address);
 
1777
        case 4:
 
1778
            return PCIDevGetDWord(aDev, u32Address);
 
1779
        default:
 
1780
            Assert(false);
 
1781
            return 0;
 
1782
    }
 
1783
}
 
1784
 
 
1785
DECLINLINE(void) ich9pciWriteBarByte(PCIDevice *aDev, int iRegion, int iOffset, uint8_t u8Val)
 
1786
{
 
1787
    PCIIORegion * pRegion = &aDev->Int.s.aIORegions[iRegion];
 
1788
 
 
1789
    int iRegionSize = pRegion->size;
 
1790
 
 
1791
    Log3(("ich9pciWriteBarByte: region=%d off=%d val=%x size=%d\n",
 
1792
         iRegion, iOffset, u8Val, iRegionSize));
 
1793
 
 
1794
    /* Region doesn't exist */
 
1795
    if (iRegionSize == 0)
 
1796
        return;
 
1797
 
 
1798
    uint32_t uAddr = ich9pciGetRegionReg(iRegion) + iOffset;
 
1799
    /* Region size must be power of two */
 
1800
    Assert((iRegionSize & (iRegionSize - 1)) == 0);
 
1801
    uint8_t uMask = (((uint32_t)iRegionSize - 1) >> (iOffset*8) ) & 0xff;
 
1802
 
 
1803
    if (iOffset == 0)
 
1804
    {
 
1805
        uMask |= (pRegion->type & PCI_ADDRESS_SPACE_IO) ?
 
1806
                (1 << 2) - 1 /* 2 lowest bits for IO region */ :
 
1807
                (1 << 4) - 1 /* 4 lowest bits for memory region, also ROM enable bit for ROM region */;
 
1808
 
 
1809
    }
 
1810
 
 
1811
    uint8_t u8Old = PCIDevGetByte(aDev, uAddr) & uMask;
 
1812
    u8Val = (u8Old & uMask) | (u8Val & ~uMask);
 
1813
 
 
1814
    Log3(("ich9pciWriteBarByte: was %x writing %x\n", u8Old, u8Val));
 
1815
 
 
1816
    PCIDevSetByte(aDev, uAddr, u8Val);
 
1817
}
 
1818
/**
 
1819
 * See paragraph 7.5 of PCI Express specification (p. 349) for definition of
 
1820
 * registers and their writability policy.
 
1821
 */
 
1822
static DECLCALLBACK(void) ich9pciConfigWriteDev(PCIDevice *aDev, uint32_t u32Address,
 
1823
                                                uint32_t val, unsigned len)
 
1824
{
 
1825
    Assert(len <= 4);
 
1826
 
 
1827
    if ((u32Address + len) > 256 && (u32Address + len) < 4096)
 
1828
    {
 
1829
        AssertMsgReturnVoid(false, ("Write to extended registers falled back to generic code\n"));
 
1830
    }
 
1831
 
 
1832
    AssertMsgReturnVoid(u32Address + len <= 256, ("Write after end of PCI config space\n"));
 
1833
 
 
1834
    if (   PCIIsMsiCapable(aDev)
 
1835
        && (u32Address >= aDev->Int.s.u8MsiCapOffset)
 
1836
        && (u32Address <  aDev->Int.s.u8MsiCapOffset + aDev->Int.s.u8MsiCapSize)
 
1837
       )
 
1838
    {
 
1839
        MsiPciConfigWrite(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
 
1840
                          aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
 
1841
                          aDev, u32Address, val, len);
 
1842
        return;
 
1843
    }
 
1844
 
 
1845
    if (   PCIIsMsixCapable(aDev)
 
1846
        && (u32Address >= aDev->Int.s.u8MsixCapOffset)
 
1847
        && (u32Address <  aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
 
1848
       )
 
1849
    {
 
1850
        MsixPciConfigWrite(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
 
1851
                           aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
 
1852
                           aDev, u32Address, val, len);
 
1853
        return;
 
1854
    }
 
1855
 
 
1856
    uint32_t addr = u32Address;
 
1857
    bool fUpdateMappings = false;
 
1858
    bool fP2PBridge = false;
 
1859
    for (uint32_t i = 0; i < len; i++)
 
1860
    {
 
1861
        bool fWritable = false;
 
1862
        bool fRom = false;
 
1863
        switch (PCIDevGetHeaderType(aDev))
 
1864
        {
 
1865
            case 0x00: /* normal device */
 
1866
            case 0x80: /* multi-function device */
 
1867
                switch (addr)
 
1868
                {
 
1869
                    /* Read-only registers  */
 
1870
                    case VBOX_PCI_VENDOR_ID: case VBOX_PCI_VENDOR_ID+1:
 
1871
                    case VBOX_PCI_DEVICE_ID: case VBOX_PCI_DEVICE_ID+1:
 
1872
                    case VBOX_PCI_REVISION_ID:
 
1873
                    case VBOX_PCI_CLASS_PROG:
 
1874
                    case VBOX_PCI_CLASS_SUB:
 
1875
                    case VBOX_PCI_CLASS_BASE:
 
1876
                    case VBOX_PCI_HEADER_TYPE:
 
1877
                    case VBOX_PCI_SUBSYSTEM_VENDOR_ID: case VBOX_PCI_SUBSYSTEM_VENDOR_ID+1:
 
1878
                    case VBOX_PCI_SUBSYSTEM_ID: case VBOX_PCI_SUBSYSTEM_ID+1:
 
1879
                    case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS+1: case VBOX_PCI_ROM_ADDRESS+2: case VBOX_PCI_ROM_ADDRESS+3:
 
1880
                    case VBOX_PCI_CAPABILITY_LIST:
 
1881
                    case VBOX_PCI_INTERRUPT_PIN:
 
1882
                        fWritable = false;
 
1883
                        break;
 
1884
                    /* Others can be written */
 
1885
                    default:
 
1886
                        fWritable = true;
 
1887
                        break;
 
1888
                }
 
1889
                break;
 
1890
            case 0x01: /* PCI-PCI bridge */
 
1891
                fP2PBridge = true;
 
1892
                switch (addr)
 
1893
                {
 
1894
                    /* Read-only registers */
 
1895
                    case VBOX_PCI_VENDOR_ID: case VBOX_PCI_VENDOR_ID+1:
 
1896
                    case VBOX_PCI_DEVICE_ID: case VBOX_PCI_DEVICE_ID+1:
 
1897
                    case VBOX_PCI_REVISION_ID:
 
1898
                    case VBOX_PCI_CLASS_PROG:
 
1899
                    case VBOX_PCI_CLASS_SUB:
 
1900
                    case VBOX_PCI_CLASS_BASE:
 
1901
                    case VBOX_PCI_HEADER_TYPE:
 
1902
                    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:
 
1903
                    case VBOX_PCI_INTERRUPT_PIN:
 
1904
                        fWritable = false;
 
1905
                        break;
 
1906
                    default:
 
1907
                        fWritable = true;
 
1908
                        break;
 
1909
                }
 
1910
                break;
 
1911
            default:
 
1912
                AssertMsgFailed(("Unknown header type %x\n", PCIDevGetHeaderType(aDev)));
 
1913
                fWritable = false;
 
1914
                break;
 
1915
        }
 
1916
 
 
1917
        uint8_t u8Val = (uint8_t)val;
 
1918
        switch (addr)
 
1919
        {
 
1920
            case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */
 
1921
                fUpdateMappings = true;
 
1922
                PCIDevSetByte(aDev, addr, u8Val);
 
1923
                break;
 
1924
            case VBOX_PCI_COMMAND+1: /* Command register, bits 8-15. */
 
1925
                /* don't change reserved bits (11-15) */
 
1926
                u8Val &= UINT32_C(~0xf8);
 
1927
                fUpdateMappings = true;
 
1928
                PCIDevSetByte(aDev, addr, u8Val);
 
1929
                break;
 
1930
            case VBOX_PCI_STATUS:  /* Status register, bits 0-7. */
 
1931
                /* don't change read-only bits => actually all lower bits are read-only */
 
1932
                u8Val &= UINT32_C(~0xff);
 
1933
                /* status register, low part: clear bits by writing a '1' to the corresponding bit */
 
1934
                aDev->config[addr] &= ~u8Val;
 
1935
                break;
 
1936
            case VBOX_PCI_STATUS+1:  /* Status register, bits 8-15. */
 
1937
                /* don't change read-only bits */
 
1938
                u8Val &= UINT32_C(~0x06);
 
1939
                /* status register, high part: clear bits by writing a '1' to the corresponding bit */
 
1940
                aDev->config[addr] &= ~u8Val;
 
1941
                break;
 
1942
            case VBOX_PCI_ROM_ADDRESS:    case VBOX_PCI_ROM_ADDRESS   +1: case VBOX_PCI_ROM_ADDRESS   +2: case VBOX_PCI_ROM_ADDRESS   +3:
 
1943
                fRom = true;
 
1944
            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:
 
1945
            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:
 
1946
            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:
 
1947
            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:
 
1948
            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:
 
1949
            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:
 
1950
            {
 
1951
                /* We check that, as same PCI register numbers as BARs may mean different registers for bridges */
 
1952
                if (fP2PBridge)
 
1953
                    goto default_case;
 
1954
                else
 
1955
                {
 
1956
                    int iRegion = fRom ? VBOX_PCI_ROM_SLOT : (addr - VBOX_PCI_BASE_ADDRESS_0) >> 2;
 
1957
                    int iOffset = addr & 0x3;
 
1958
                    ich9pciWriteBarByte(aDev, iRegion, iOffset, u8Val);
 
1959
                    fUpdateMappings = true;
 
1960
                }
 
1961
                break;
 
1962
            }
 
1963
            default:
 
1964
            default_case:
 
1965
                if (fWritable)
 
1966
                    PCIDevSetByte(aDev, addr, u8Val);
 
1967
        }
 
1968
        addr++;
 
1969
        val >>= 8;
 
1970
    }
 
1971
 
 
1972
    if (fUpdateMappings)
 
1973
        /* if the command/base address register is modified, we must modify the mappings */
 
1974
        ich9pciUpdateMappings(aDev);
 
1975
}
 
1976
 
 
1977
/* Slot/functions assignment per table at p. 12 of ICH9 family spec update */
 
1978
static const struct {
 
1979
    const char* pszName;
 
1980
    int32_t     iSlot;
 
1981
    int32_t     iFunction;
 
1982
} PciSlotAssignments[] = {
 
1983
    /* The only override that have to be here, as host controller is added in the way invisible to bus slot assignment management,
 
1984
       maybe to be changed in the future. */
 
1985
    {
 
1986
        "i82801",   30, 0 /* Host Controller */
 
1987
    },
 
1988
};
 
1989
 
 
1990
static bool assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName, int iDevFn, PciAddress* aPosition)
 
1991
{
 
1992
    aPosition->iBus = 0;
 
1993
    aPosition->iDeviceFunc = iDevFn;
 
1994
    aPosition->iRegister = 0; /* N/A */
 
1995
 
 
1996
    /* Hardcoded slots/functions, per chipset spec */
 
1997
    for (size_t i = 0; i < RT_ELEMENTS(PciSlotAssignments); i++)
 
1998
    {
 
1999
        if (!strcmp(pszName, PciSlotAssignments[i].pszName))
 
2000
        {
 
2001
            PCISetRequestedDevfunc(pPciDev);
 
2002
            aPosition->iDeviceFunc =
 
2003
                    (PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
 
2004
            return true;
 
2005
        }
 
2006
    }
 
2007
 
 
2008
    /* Explicit slot request */
 
2009
    if (iDevFn >=0 && iDevFn < (int)RT_ELEMENTS(pBus->apDevices))
 
2010
        return true;
 
2011
 
 
2012
    int iStartPos = 0;
 
2013
 
 
2014
    /* Otherwise when assigning a slot, we need to make sure all its functions are available */
 
2015
    for (int iPos = iStartPos; iPos < (int)RT_ELEMENTS(pBus->apDevices); iPos += 8)
 
2016
    {
 
2017
        if (        !pBus->apDevices[iPos]
 
2018
                &&  !pBus->apDevices[iPos + 1]
 
2019
                &&  !pBus->apDevices[iPos + 2]
 
2020
                &&  !pBus->apDevices[iPos + 3]
 
2021
                &&  !pBus->apDevices[iPos + 4]
 
2022
                &&  !pBus->apDevices[iPos + 5]
 
2023
                &&  !pBus->apDevices[iPos + 6]
 
2024
                &&  !pBus->apDevices[iPos + 7])
 
2025
        {
 
2026
            PCIClearRequestedDevfunc(pPciDev);
 
2027
            aPosition->iDeviceFunc = iPos;
 
2028
            return true;
 
2029
        }
 
2030
    }
 
2031
 
 
2032
    return false;
 
2033
}
 
2034
 
 
2035
static bool hasHardAssignedDevsInSlot(PPCIBUS pBus, int iSlot)
 
2036
{
 
2037
    PCIDevice** aSlot = &pBus->apDevices[iSlot << 3];
 
2038
 
 
2039
    return     (aSlot[0] && PCIIsRequestedDevfunc(aSlot[0]))
 
2040
            || (aSlot[1] && PCIIsRequestedDevfunc(aSlot[1]))
 
2041
            || (aSlot[2] && PCIIsRequestedDevfunc(aSlot[2]))
 
2042
            || (aSlot[3] && PCIIsRequestedDevfunc(aSlot[3]))
 
2043
            || (aSlot[4] && PCIIsRequestedDevfunc(aSlot[4]))
 
2044
            || (aSlot[5] && PCIIsRequestedDevfunc(aSlot[5]))
 
2045
            || (aSlot[6] && PCIIsRequestedDevfunc(aSlot[6]))
 
2046
            || (aSlot[7] && PCIIsRequestedDevfunc(aSlot[7]))
 
2047
           ;
 
2048
}
 
2049
 
 
2050
static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
 
2051
{
 
2052
    PciAddress aPosition = {0, 0, 0};
 
2053
 
 
2054
    /*
 
2055
     * Find device position
 
2056
     */
 
2057
    if (!assignPosition(pBus, pPciDev, pszName, iDev, &aPosition))
 
2058
    {
 
2059
        AssertMsgFailed(("Couldn't asssign position!\n"));
 
2060
        return VERR_PDM_TOO_PCI_MANY_DEVICES;
 
2061
    }
 
2062
 
 
2063
    AssertMsgReturn(aPosition.iBus == 0,
 
2064
                    ("Assigning behind the bridge not implemented yet\n"),
 
2065
                    VERR_PDM_TOO_PCI_MANY_DEVICES);
 
2066
 
 
2067
 
 
2068
    iDev = aPosition.iDeviceFunc;
 
2069
    /*
 
2070
     * Check if we can really take this slot, possibly by relocating
 
2071
     * its current habitant, if it wasn't hard assigned too.
 
2072
     */
 
2073
    if (PCIIsRequestedDevfunc(pPciDev) &&
 
2074
        pBus->apDevices[iDev]          &&
 
2075
        PCIIsRequestedDevfunc(pBus->apDevices[iDev]))
 
2076
    {
 
2077
        AssertReleaseMsgFailed(("Configuration error:'%s' and '%s' are both configured as device %d\n",
 
2078
                                 pszName, pBus->apDevices[iDev]->name, iDev));
 
2079
        return VERR_INTERNAL_ERROR;
 
2080
    }
 
2081
 
 
2082
    if (pBus->apDevices[iDev])
 
2083
    {
 
2084
        /* if we got here, we shall (and usually can) relocate the device */
 
2085
        bool assigned = assignPosition(pBus, pBus->apDevices[iDev], pBus->apDevices[iDev]->name, -1, &aPosition);
 
2086
        AssertMsgReturn(aPosition.iBus == 0,
 
2087
                        ("Assigning behind the bridge not implemented yet\n"),
 
2088
                        VERR_PDM_TOO_PCI_MANY_DEVICES);
 
2089
        int iRelDev = aPosition.iDeviceFunc;
 
2090
        if (!assigned || iRelDev == iDev)
 
2091
        {
 
2092
            AssertMsgFailed(("Couldn't find free spot!\n"));
 
2093
            return VERR_PDM_TOO_PCI_MANY_DEVICES;
 
2094
        }
 
2095
        /* Copy device function by function to its new position */
 
2096
        for (int i = 0; i < 8; i++)
 
2097
        {
 
2098
            if (!pBus->apDevices[iDev + i])
 
2099
                continue;
 
2100
            Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->apDevices[iDev + i]->name, iDev + i, iRelDev + i));
 
2101
            pBus->apDevices[iRelDev + i] = pBus->apDevices[iDev + i];
 
2102
            pBus->apDevices[iRelDev + i]->devfn = iRelDev + i;
 
2103
            pBus->apDevices[iDev + i] = NULL;
 
2104
        }
 
2105
    }
 
2106
 
 
2107
    /*
 
2108
     * Fill in device information.
 
2109
     */
 
2110
    pPciDev->devfn                  = iDev;
 
2111
    pPciDev->name                   = pszName;
 
2112
    pPciDev->Int.s.pBusR3           = pBus;
 
2113
    pPciDev->Int.s.pBusR0           = MMHyperR3ToR0(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
 
2114
    pPciDev->Int.s.pBusRC           = MMHyperR3ToRC(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
 
2115
    pPciDev->Int.s.pfnConfigRead    = ich9pciConfigReadDev;
 
2116
    pPciDev->Int.s.pfnConfigWrite   = ich9pciConfigWriteDev;
 
2117
    pBus->apDevices[iDev]           = pPciDev;
 
2118
    if (PCIIsPci2PciBridge(pPciDev))
 
2119
    {
 
2120
        AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->apDevices), ("Number of bridges exceeds the number of possible devices on the bus\n"));
 
2121
        AssertMsg(pPciDev->Int.s.pfnBridgeConfigRead && pPciDev->Int.s.pfnBridgeConfigWrite,
 
2122
                  ("device is a bridge but does not implement read/write functions\n"));
 
2123
        pBus->papBridgesR3[pBus->cBridges] = pPciDev;
 
2124
        pBus->cBridges++;
 
2125
    }
 
2126
 
 
2127
    Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
 
2128
         iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
 
2129
 
 
2130
    return VINF_SUCCESS;
 
2131
}
 
2132
 
 
2133
static void printIndent(PCDBGFINFOHLP pHlp, int iIndent)
 
2134
{
 
2135
    for (int i = 0; i < iIndent; i++)
 
2136
    {
 
2137
        pHlp->pfnPrintf(pHlp, "    ");
 
2138
    }
 
2139
}
 
2140
 
 
2141
static void ich9pciBusInfo(PPCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bool fRegisters)
 
2142
{
 
2143
    for (uint32_t iDev = 0; iDev < RT_ELEMENTS(pBus->apDevices); iDev++)
 
2144
    {
 
2145
        PPCIDEVICE pPciDev = pBus->apDevices[iDev];
 
2146
        if (pPciDev != NULL)
 
2147
        {
 
2148
            printIndent(pHlp, iIndent);
 
2149
            pHlp->pfnPrintf(pHlp, "%02x:%02x:%02x %s: %04x-%04x%s%s",
 
2150
                            pBus->iBus, (iDev >> 3) & 0xff, iDev & 0x7,
 
2151
                            pPciDev->name,
 
2152
                            PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev),
 
2153
                            PCIIsMsiCapable(pPciDev)  ? " MSI" : "",
 
2154
                            PCIIsMsixCapable(pPciDev) ? " MSI-X" : ""
 
2155
                            );
 
2156
            if (PCIDevGetInterruptPin(pPciDev) != 0)
 
2157
                pHlp->pfnPrintf(pHlp, " IRQ%d", PCIDevGetInterruptLine(pPciDev));
 
2158
 
 
2159
            pHlp->pfnPrintf(pHlp, "\n");
 
2160
 
 
2161
            int iCmd = PCIDevGetCommand(pPciDev);
 
2162
            if ((iCmd & (VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY)) != 0)
 
2163
            {
 
2164
                for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
 
2165
                {
 
2166
                    PCIIORegion* pRegion = &pPciDev->Int.s.aIORegions[iRegion];
 
2167
                    int32_t  iRegionSize = pRegion->size;
 
2168
 
 
2169
                    if (iRegionSize == 0)
 
2170
                        continue;
 
2171
 
 
2172
                    uint32_t u32Addr = ich9pciConfigReadDev(pPciDev, ich9pciGetRegionReg(iRegion), 4);
 
2173
                    const char * szDesc;
 
2174
 
 
2175
                    if (pRegion->type & PCI_ADDRESS_SPACE_IO)
 
2176
                    {
 
2177
                        szDesc = "IO";
 
2178
                        u32Addr &= ~0x3;
 
2179
                    }
 
2180
                    else
 
2181
                    {
 
2182
                        szDesc = "MMIO";
 
2183
                        u32Addr &= ~0xf;
 
2184
                    }
 
2185
 
 
2186
                    printIndent(pHlp, iIndent + 2);
 
2187
                    pHlp->pfnPrintf(pHlp, "  %s region #%d: %x..%x\n",
 
2188
                                    szDesc, iRegion, u32Addr, u32Addr+iRegionSize);
 
2189
                }
 
2190
            }
 
2191
 
 
2192
            if (fRegisters)
 
2193
            {
 
2194
                printIndent(pHlp, iIndent + 2);
 
2195
                pHlp->pfnPrintf(pHlp, "  PCI registers:\n");
 
2196
                for (int iReg = 0; iReg < 0x100; )
 
2197
                {
 
2198
                    int iPerLine = 0x10;
 
2199
                    Assert (0x100 % iPerLine == 0);
 
2200
                    printIndent(pHlp, iIndent + 3);
 
2201
 
 
2202
                    while (iPerLine-- > 0)
 
2203
                    {
 
2204
                        pHlp->pfnPrintf(pHlp, "%02x ", pPciDev->config[iReg++]);
 
2205
                    }
 
2206
                    pHlp->pfnPrintf(pHlp, "\n");
 
2207
                }
 
2208
            }
 
2209
        }
 
2210
    }
 
2211
 
 
2212
    if (pBus->cBridges > 0)
 
2213
    {
 
2214
        printIndent(pHlp, iIndent);
 
2215
        pHlp->pfnPrintf(pHlp, "Registered %d bridges, subordinate buses info follows\n", pBus->cBridges);
 
2216
        for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
 
2217
        {
 
2218
            PPCIBUS pBusSub = PDMINS_2_DATA(pBus->papBridgesR3[iBridge]->pDevIns, PPCIBUS);
 
2219
            ich9pciBusInfo(pBusSub, pHlp, iIndent + 1, fRegisters);
 
2220
        }
 
2221
    }
 
2222
}
 
2223
 
 
2224
/**
 
2225
 * Info handler, device version.
 
2226
 *
 
2227
 * @param   pDevIns     Device instance which registered the info.
 
2228
 * @param   pHlp        Callback functions for doing output.
 
2229
 * @param   pszArgs     Argument string. Optional and specific to the handler.
 
2230
 */
 
2231
static DECLCALLBACK(void) ich9pciInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
 
2232
{
 
2233
    PPCIBUS pBus = DEVINS_2_PCIBUS(pDevIns);
 
2234
 
 
2235
    if (pszArgs == NULL || !strcmp(pszArgs, "basic"))
 
2236
    {
 
2237
        ich9pciBusInfo(pBus, pHlp, 0, false);
 
2238
    }
 
2239
    else if (!strcmp(pszArgs, "verbose"))
 
2240
    {
 
2241
        ich9pciBusInfo(pBus, pHlp, 0, true);
 
2242
    }
 
2243
    else
 
2244
    {
 
2245
        pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'verbose'.\n");
 
2246
    }
 
2247
}
 
2248
 
 
2249
 
 
2250
static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns,
 
2251
                                          int        iInstance,
 
2252
                                          PCFGMNODE  pCfg)
 
2253
{
 
2254
    int rc;
 
2255
    Assert(iInstance == 0);
 
2256
 
 
2257
    /*
 
2258
     * Validate and read configuration.
 
2259
     */
 
2260
    if (!CFGMR3AreValuesValid(pCfg,
 
2261
                              "IOAPIC\0"
 
2262
                              "GCEnabled\0"
 
2263
                              "R0Enabled\0"
 
2264
                              "McfgBase\0"
 
2265
                              "McfgLength\0"
 
2266
                              ))
 
2267
        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
 
2268
 
 
2269
    /* query whether we got an IOAPIC */
 
2270
    bool fUseIoApic;
 
2271
    rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fUseIoApic, false);
 
2272
    if (RT_FAILURE(rc))
 
2273
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2274
                                N_("Configuration error: Failed to query boolean value \"IOAPIC\""));
 
2275
 
 
2276
    /* check if RC code is enabled. */
 
2277
    bool fGCEnabled;
 
2278
    rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
 
2279
    if (RT_FAILURE(rc))
 
2280
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2281
                                N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
 
2282
 
 
2283
    /* check if R0 code is enabled. */
 
2284
    bool fR0Enabled;
 
2285
    rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
 
2286
    if (RT_FAILURE(rc))
 
2287
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2288
                                N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
 
2289
 
 
2290
    Log(("PCI: fUseIoApic=%RTbool fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fUseIoApic, fGCEnabled, fR0Enabled));
 
2291
 
 
2292
    /*
 
2293
     * Init data.
 
2294
     */
 
2295
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
2296
    PPCIBUS     pBus     = &pGlobals->aPciBus;
 
2297
    /* Zero out everything */
 
2298
    memset(pGlobals, 0, sizeof(*pGlobals));
 
2299
    /* And fill values */
 
2300
    if (!fUseIoApic)
 
2301
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2302
                                N_("Must use IO-APIC with ICH9 chipset"));
 
2303
    rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pGlobals->u64PciConfigMMioAddress, 0);
 
2304
    if (RT_FAILURE(rc))
 
2305
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2306
                                N_("Configuration error: Failed to read \"McfgBase\""));
 
2307
    rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pGlobals->u64PciConfigMMioLength, 0);
 
2308
    if (RT_FAILURE(rc))
 
2309
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2310
                                N_("Configuration error: Failed to read \"McfgLength\""));
 
2311
 
 
2312
    pGlobals->pDevInsR3 = pDevIns;
 
2313
    pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
 
2314
    pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2315
 
 
2316
    pGlobals->aPciBus.pDevInsR3 = pDevIns;
 
2317
    pGlobals->aPciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
 
2318
    pGlobals->aPciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2319
    pGlobals->aPciBus.papBridgesR3 = (PPCIDEVICE *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPCIDEVICE) * RT_ELEMENTS(pGlobals->aPciBus.apDevices));
 
2320
 
 
2321
    /*
 
2322
     * Register bus
 
2323
     */
 
2324
    PDMPCIBUSREG PciBusReg;
 
2325
    PciBusReg.u32Version              = PDM_PCIBUSREG_VERSION;
 
2326
    PciBusReg.pfnRegisterR3           = ich9pciRegister;
 
2327
    PciBusReg.pfnRegisterMsiR3        = ich9pciRegisterMsi;
 
2328
    PciBusReg.pfnIORegionRegisterR3   = ich9pciIORegionRegister;
 
2329
    PciBusReg.pfnSetConfigCallbacksR3 = ich9pciSetConfigCallbacks;
 
2330
    PciBusReg.pfnSetIrqR3             = ich9pciSetIrq;
 
2331
    PciBusReg.pfnSaveExecR3           = ich9pciGenericSaveExec;
 
2332
    PciBusReg.pfnLoadExecR3           = ich9pciGenericLoadExec;
 
2333
    PciBusReg.pfnFakePCIBIOSR3        = ich9pciFakePCIBIOS;
 
2334
    PciBusReg.pszSetIrqRC             = fGCEnabled ? "ich9pciSetIrq" : NULL;
 
2335
    PciBusReg.pszSetIrqR0             = fR0Enabled ? "ich9pciSetIrq" : NULL;
 
2336
    rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
 
2337
    if (RT_FAILURE(rc))
 
2338
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2339
                                N_("Failed to register ourselves as a PCI Bus"));
 
2340
    if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
 
2341
        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
 
2342
                                   N_("PCI helper version mismatch; got %#x expected %#x"),
 
2343
                                   pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
 
2344
 
 
2345
    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
 
2346
    pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
 
2347
 
 
2348
    /*
 
2349
     * Fill in PCI configs and add them to the bus.
 
2350
     */
 
2351
 
 
2352
    /**
 
2353
     * We emulate 82801IB ICH9 IO chip used in Q35,
 
2354
     * see http://ark.intel.com/Product.aspx?id=31892
 
2355
     *
 
2356
     * Stepping   S-Spec   Top Marking
 
2357
     *
 
2358
     *   A2        SLA9M    NH82801IB
 
2359
     */
 
2360
    /* Host bridge device */
 
2361
    /* @todo: move to separate driver? */
 
2362
    PCIDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
 
2363
    PCIDevSetDeviceId(  &pBus->aPciDev, 0x244e); /* Desktop */
 
2364
    PCIDevSetRevisionId(&pBus->aPciDev,   0x92); /* rev. A2 */
 
2365
    PCIDevSetClassBase( &pBus->aPciDev,   0x06); /* bridge */
 
2366
    PCIDevSetClassSub(  &pBus->aPciDev,   0x04); /* Host/PCI bridge */
 
2367
    PCIDevSetClassProg( &pBus->aPciDev,   0x01); /* Supports subtractive decoding. */
 
2368
    PCIDevSetHeaderType(&pBus->aPciDev,   0x01); /* bridge */
 
2369
    PCIDevSetWord(&pBus->aPciDev,  VBOX_PCI_SEC_STATUS, 0x0280);  /* secondary status */
 
2370
    PCIDevSetDWord(&pBus->aPciDev, 0x4c, 0x00001200); /* Bridge policy configuration */
 
2371
    PCIDevSetStatus    (&pBus->aPciDev, VBOX_PCI_STATUS_CAP_LIST);
 
2372
    PCIDevSetCapabilityList(&pBus->aPciDev, 0x50);
 
2373
    /* capability */
 
2374
    PCIDevSetWord(&pBus->aPciDev,  0x50, VBOX_PCI_CAP_ID_SSVID);
 
2375
    PCIDevSetDWord(&pBus->aPciDev, 0x54, 0x00000000); /* Subsystem vendor ids */
 
2376
 
 
2377
    pBus->aPciDev.pDevIns               = pDevIns;
 
2378
    /* We register Host<->PCI controller on the bus */
 
2379
    ich9pciRegisterInternal(pBus, -1, &pBus->aPciDev, "i82801");
 
2380
 
 
2381
    /*
 
2382
     * Register I/O ports and save state.
 
2383
     */
 
2384
    rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 1, NULL, ich9pciIOPortAddressWrite, ich9pciIOPortAddressRead, NULL, NULL, "ICH9 (PCI)");
 
2385
    if (RT_FAILURE(rc))
 
2386
        return rc;
 
2387
    rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cfc, 4, NULL, ich9pciIOPortDataWrite, ich9pciIOPortDataRead, NULL, NULL, "ICH9 (PCI)");
 
2388
    if (RT_FAILURE(rc))
 
2389
        return rc;
 
2390
    if (fGCEnabled)
 
2391
    {
 
2392
        rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cf8, 1, NIL_RTGCPTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
 
2393
        if (RT_FAILURE(rc))
 
2394
            return rc;
 
2395
        rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cfc, 4, NIL_RTGCPTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
 
2396
        if (RT_FAILURE(rc))
 
2397
            return rc;
 
2398
    }
 
2399
    if (fR0Enabled)
 
2400
    {
 
2401
        rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cf8, 1, NIL_RTR0PTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
 
2402
        if (RT_FAILURE(rc))
 
2403
            return rc;
 
2404
        rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cfc, 4, NIL_RTR0PTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
 
2405
        if (RT_FAILURE(rc))
 
2406
            return rc;
 
2407
    }
 
2408
 
 
2409
    if (pGlobals->u64PciConfigMMioAddress != 0)
 
2410
    {
 
2411
        rc = PDMDevHlpMMIORegister(pDevIns,
 
2412
                                   pGlobals->u64PciConfigMMioAddress,
 
2413
                                   pGlobals->u64PciConfigMMioLength,
 
2414
                                   0,
 
2415
                                   ich9pciMcfgMMIOWrite,
 
2416
                                   ich9pciMcfgMMIORead,
 
2417
                                   NULL /* fill */,
 
2418
                                   "MCFG ranges");
 
2419
        if (RT_FAILURE(rc))
 
2420
        {
 
2421
            AssertMsgRC(rc, ("Cannot register MCFG MMIO: %Rrc\n", rc));
 
2422
            return rc;
 
2423
        }
 
2424
 
 
2425
        if (fGCEnabled)
 
2426
        {
 
2427
 
 
2428
            rc = PDMDevHlpMMIORegisterRC(pDevIns,
 
2429
                                         pGlobals->u64PciConfigMMioAddress,
 
2430
                                         pGlobals->u64PciConfigMMioLength,
 
2431
                                         0,
 
2432
                                         "ich9pciMcfgMMIOWrite",
 
2433
                                         "ich9pciMcfgMMIORead",
 
2434
                                         NULL /* fill */);
 
2435
            if (RT_FAILURE(rc))
 
2436
            {
 
2437
                AssertMsgRC(rc, ("Cannot register MCFG MMIO (GC): %Rrc\n", rc));
 
2438
                return rc;
 
2439
            }
 
2440
        }
 
2441
 
 
2442
 
 
2443
        if (fR0Enabled)
 
2444
        {
 
2445
 
 
2446
            rc = PDMDevHlpMMIORegisterR0(pDevIns,
 
2447
                                         pGlobals->u64PciConfigMMioAddress,
 
2448
                                         pGlobals->u64PciConfigMMioLength,
 
2449
                                         0,
 
2450
                                         "ich9pciMcfgMMIOWrite",
 
2451
                                         "ich9pciMcfgMMIORead",
 
2452
                                         NULL /* fill */);
 
2453
            if (RT_FAILURE(rc))
 
2454
            {
 
2455
                AssertMsgRC(rc, ("Cannot register MCFG MMIO (R0): %Rrc\n", rc));
 
2456
                return rc;
 
2457
            }
 
2458
        }
 
2459
    }
 
2460
 
 
2461
    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
 
2462
                                sizeof(*pBus) + 16*128, "pgm",
 
2463
                                NULL, NULL, NULL,
 
2464
                                NULL, ich9pciR3SaveExec, NULL,
 
2465
                                NULL, ich9pciR3LoadExec, NULL);
 
2466
    if (RT_FAILURE(rc))
 
2467
        return rc;
 
2468
 
 
2469
 
 
2470
    /** @todo: other chipset devices shall be registered too */
 
2471
    /** @todo: what to with bridges? */
 
2472
 
 
2473
    PDMDevHlpDBGFInfoRegister(pDevIns, "pci", "Display PCI bus status. (no arguments)", ich9pciInfo);
 
2474
 
 
2475
    return VINF_SUCCESS;
 
2476
}
 
2477
 
 
2478
static void ich9pciResetDevice(PPCIDEVICE pDev)
 
2479
{
 
2480
    PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
 
2481
    int rc;
 
2482
 
 
2483
    /* Clear regions */
 
2484
    for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
 
2485
    {
 
2486
        PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
 
2487
        if (pRegion->size == 0)
 
2488
            continue;
 
2489
 
 
2490
        ich9pciUnmapRegion(pDev, iRegion);
 
2491
    }
 
2492
 
 
2493
    PCIDevSetCommand(pDev,
 
2494
                     PCIDevGetCommand(pDev)
 
2495
                     &
 
2496
                     ~(VBOX_PCI_COMMAND_IO |
 
2497
                       VBOX_PCI_COMMAND_MEMORY |
 
2498
                       VBOX_PCI_COMMAND_MASTER));
 
2499
 
 
2500
    /* Bridge device reset handlers processed later */
 
2501
    if (!PCIIsPci2PciBridge(pDev))
 
2502
    {
 
2503
        PCIDevSetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
 
2504
        PCIDevSetInterruptLine(pDev, 0x0);
 
2505
    }
 
2506
}
 
2507
 
 
2508
 
 
2509
/**
 
2510
 * @copydoc FNPDMDEVRESET
 
2511
 */
 
2512
static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
 
2513
{
 
2514
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
2515
    PPCIBUS     pBus     = &pGlobals->aPciBus;
 
2516
 
 
2517
    /* PCI-specific reset for each device. */
 
2518
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
2519
    {
 
2520
        if (pBus->apDevices[i])
 
2521
            ich9pciResetDevice(pBus->apDevices[i]);
 
2522
    }
 
2523
 
 
2524
    for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
 
2525
    {
 
2526
        if (pBus->papBridgesR3[iBridge])
 
2527
            ich9pcibridgeReset(pBus->papBridgesR3[iBridge]->pDevIns);
 
2528
    }
 
2529
 
 
2530
    ich9pciFakePCIBIOS(pDevIns);
 
2531
}
 
2532
 
 
2533
static void ich9pciRelocateDevice(PPCIDEVICE pDev, RTGCINTPTR offDelta)
 
2534
{
 
2535
    if (pDev)
 
2536
    {
 
2537
        pDev->Int.s.pBusRC += offDelta;
 
2538
        if (pDev->Int.s.pMsixPageRC)
 
2539
            pDev->Int.s.pMsixPageRC += offDelta;
 
2540
    }
 
2541
}
 
2542
 
 
2543
/**
 
2544
 * @copydoc FNPDMDEVRELOCATE
 
2545
 */
 
2546
static DECLCALLBACK(void) ich9pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
 
2547
{
 
2548
    PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
 
2549
    PPCIBUS     pBus     = &pGlobals->aPciBus;
 
2550
    pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2551
 
 
2552
    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
 
2553
    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2554
 
 
2555
    /* Relocate RC pointers for the attached pci devices. */
 
2556
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
2557
        ich9pciRelocateDevice(pBus->apDevices[i], offDelta);
 
2558
 
 
2559
}
 
2560
 
 
2561
/**
 
2562
 * @interface_method_impl{PDMDEVREG,pfnConstruct}
 
2563
 */
 
2564
static DECLCALLBACK(int)   ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
 
2565
                                                  int        iInstance,
 
2566
                                                  PCFGMNODE  pCfg)
 
2567
{
 
2568
    int rc;
 
2569
 
 
2570
    /*
 
2571
     * Validate and read configuration.
 
2572
     */
 
2573
    if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
 
2574
        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
 
2575
 
 
2576
    /* check if RC code is enabled. */
 
2577
    bool fGCEnabled;
 
2578
    rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
 
2579
    if (RT_FAILURE(rc))
 
2580
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2581
                                N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
 
2582
 
 
2583
    /* check if R0 code is enabled. */
 
2584
    bool fR0Enabled;
 
2585
    rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
 
2586
    if (RT_FAILURE(rc))
 
2587
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2588
                                N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
 
2589
    Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
 
2590
 
 
2591
    /*
 
2592
     * Init data and register the PCI bus.
 
2593
     */
 
2594
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2595
    pBus->pDevInsR3 = pDevIns;
 
2596
    pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
 
2597
    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2598
    pBus->papBridgesR3 = (PPCIDEVICE *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPCIDEVICE) * RT_ELEMENTS(pBus->apDevices));
 
2599
 
 
2600
    PDMPCIBUSREG PciBusReg;
 
2601
    PciBusReg.u32Version              = PDM_PCIBUSREG_VERSION;
 
2602
    PciBusReg.pfnRegisterR3           = ich9pcibridgeRegister;
 
2603
    PciBusReg.pfnRegisterMsiR3        = ich9pciRegisterMsi;
 
2604
    PciBusReg.pfnIORegionRegisterR3   = ich9pciIORegionRegister;
 
2605
    PciBusReg.pfnSetConfigCallbacksR3 = ich9pciSetConfigCallbacks;
 
2606
    PciBusReg.pfnSetIrqR3             = ich9pcibridgeSetIrq;
 
2607
    PciBusReg.pfnSaveExecR3           = ich9pciGenericSaveExec;
 
2608
    PciBusReg.pfnLoadExecR3           = ich9pciGenericLoadExec;
 
2609
    PciBusReg.pfnFakePCIBIOSR3        = NULL; /* Only needed for the first bus. */
 
2610
    PciBusReg.pszSetIrqRC             = fGCEnabled ? "ich9pcibridgeSetIrq" : NULL;
 
2611
    PciBusReg.pszSetIrqR0             = fR0Enabled ? "ich9pcibridgeSetIrq" : NULL;
 
2612
    rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
 
2613
    if (RT_FAILURE(rc))
 
2614
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
2615
                                N_("Failed to register ourselves as a PCI Bus"));
 
2616
    if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
 
2617
        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
 
2618
                                   N_("PCI helper version mismatch; got %#x expected %#x"),
 
2619
                                   pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
 
2620
 
 
2621
    pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
 
2622
    pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
 
2623
 
 
2624
    /*
 
2625
     * Fill in PCI configs and add them to the bus.
 
2626
     */
 
2627
    PCIDevSetVendorId(  &pBus->aPciDev, 0x8086); /* Intel */
 
2628
    PCIDevSetDeviceId(  &pBus->aPciDev, 0x2448); /* 82801 Mobile PCI bridge. */
 
2629
    PCIDevSetRevisionId(&pBus->aPciDev,   0xf2);
 
2630
    PCIDevSetClassSub(  &pBus->aPciDev,   0x04); /* pci2pci */
 
2631
    PCIDevSetClassBase( &pBus->aPciDev,   0x06); /* PCI_bridge */
 
2632
    PCIDevSetClassProg( &pBus->aPciDev,   0x01); /* Supports subtractive decoding. */
 
2633
    PCIDevSetHeaderType(&pBus->aPciDev,   0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */
 
2634
    PCIDevSetCommand(   &pBus->aPciDev,   0x00);
 
2635
    PCIDevSetStatus(    &pBus->aPciDev,   0x20); /* 66MHz Capable. */
 
2636
    PCIDevSetInterruptLine(&pBus->aPciDev, 0x00); /* This device does not assert interrupts. */
 
2637
 
 
2638
    /*
 
2639
     * This device does not generate interrupts. Interrupt delivery from
 
2640
     * devices attached to the bus is unaffected.
 
2641
     */
 
2642
    PCIDevSetInterruptPin (&pBus->aPciDev, 0x00);
 
2643
 
 
2644
    pBus->aPciDev.pDevIns                    = pDevIns;
 
2645
 
 
2646
    /* Bridge-specific data */
 
2647
    PCISetPci2PciBridge(&pBus->aPciDev);
 
2648
    pBus->aPciDev.Int.s.pfnBridgeConfigRead  = ich9pcibridgeConfigRead;
 
2649
    pBus->aPciDev.Int.s.pfnBridgeConfigWrite = ich9pcibridgeConfigWrite;
 
2650
 
 
2651
    /*
 
2652
     * Register this PCI bridge. The called function will take care on which bus we will get registered.
 
2653
     */
 
2654
    rc = PDMDevHlpPCIRegister (pDevIns, &pBus->aPciDev);
 
2655
    if (RT_FAILURE(rc))
 
2656
        return rc;
 
2657
 
 
2658
    /*
 
2659
     * The iBus property doesn't really represent the bus number
 
2660
     * because the guest and the BIOS can choose different bus numbers
 
2661
     * for them.
 
2662
     * The bus number is mainly for the setIrq function to indicate
 
2663
     * when the host bus is reached which will have iBus = 0.
 
2664
     * That's why the + 1.
 
2665
     */
 
2666
    pBus->iBus = iInstance + 1;
 
2667
 
 
2668
    /*
 
2669
     * Register SSM handlers. We use the same saved state version as for the host bridge
 
2670
     * to make changes easier.
 
2671
     */
 
2672
    rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
 
2673
                                sizeof(*pBus) + 16*128,
 
2674
                                "pgm" /* before */,
 
2675
                                NULL, NULL, NULL,
 
2676
                                NULL, ich9pcibridgeR3SaveExec, NULL,
 
2677
                                NULL, ich9pcibridgeR3LoadExec, NULL);
 
2678
    if (RT_FAILURE(rc))
 
2679
        return rc;
 
2680
 
 
2681
 
 
2682
    return VINF_SUCCESS;
 
2683
}
 
2684
 
 
2685
/**
 
2686
 * @copydoc FNPDMDEVRESET
 
2687
 */
 
2688
static void ich9pcibridgeReset(PPDMDEVINS pDevIns)
 
2689
{
 
2690
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2691
 
 
2692
    /* Reset config space to default values. */
 
2693
    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_PRIMARY_BUS, 0);
 
2694
    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_SECONDARY_BUS, 0);
 
2695
    PCIDevSetByte(&pBus->aPciDev, VBOX_PCI_SUBORDINATE_BUS, 0);
 
2696
 
 
2697
    /* PCI-specific reset for each device. */
 
2698
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
2699
    {
 
2700
        if (pBus->apDevices[i])
 
2701
            ich9pciResetDevice(pBus->apDevices[i]);
 
2702
    }
 
2703
}
 
2704
 
 
2705
 
 
2706
/**
 
2707
 * @copydoc FNPDMDEVRELOCATE
 
2708
 */
 
2709
static DECLCALLBACK(void) ich9pcibridgeRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
 
2710
{
 
2711
    PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
 
2712
    pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
 
2713
 
 
2714
    /* Relocate RC pointers for the attached pci devices. */
 
2715
    for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
 
2716
        ich9pciRelocateDevice(pBus->apDevices[i], offDelta);
 
2717
}
 
2718
 
 
2719
/**
 
2720
 * The PCI bus device registration structure.
 
2721
 */
 
2722
const PDMDEVREG g_DevicePciIch9 =
 
2723
{
 
2724
    /* u32Version */
 
2725
    PDM_DEVREG_VERSION,
 
2726
    /* szName */
 
2727
    "ich9pci",
 
2728
    /* szRCMod */
 
2729
    "VBoxDDGC.gc",
 
2730
    /* szR0Mod */
 
2731
    "VBoxDDR0.r0",
 
2732
    /* pszDescription */
 
2733
    "ICH9 PCI bridge",
 
2734
    /* fFlags */
 
2735
    PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
 
2736
    /* fClass */
 
2737
    PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
 
2738
    /* cMaxInstances */
 
2739
    1,
 
2740
    /* cbInstance */
 
2741
    sizeof(PCIGLOBALS),
 
2742
    /* pfnConstruct */
 
2743
    ich9pciConstruct,
 
2744
    /* pfnDestruct */
 
2745
    NULL,
 
2746
    /* pfnRelocate */
 
2747
    ich9pciRelocate,
 
2748
    /* pfnIOCtl */
 
2749
    NULL,
 
2750
    /* pfnPowerOn */
 
2751
    NULL,
 
2752
    /* pfnReset */
 
2753
    ich9pciReset,
 
2754
    /* pfnSuspend */
 
2755
    NULL,
 
2756
    /* pfnResume */
 
2757
    NULL,
 
2758
    /* pfnAttach */
 
2759
    NULL,
 
2760
    /* pfnDetach */
 
2761
    NULL,
 
2762
    /* pfnQueryInterface */
 
2763
    NULL,
 
2764
    /* pfnInitComplete */
 
2765
    NULL,
 
2766
    /* pfnPowerOff */
 
2767
    NULL,
 
2768
    /* pfnSoftReset */
 
2769
    NULL,
 
2770
    /* u32VersionEnd */
 
2771
    PDM_DEVREG_VERSION
 
2772
};
 
2773
 
 
2774
/**
 
2775
 * The device registration structure
 
2776
 * for the PCI-to-PCI bridge.
 
2777
 */
 
2778
const PDMDEVREG g_DevicePciIch9Bridge =
 
2779
{
 
2780
    /* u32Version */
 
2781
    PDM_DEVREG_VERSION,
 
2782
    /* szName */
 
2783
    "ich9pcibridge",
 
2784
    /* szRCMod */
 
2785
    "VBoxDDGC.gc",
 
2786
    /* szR0Mod */
 
2787
    "VBoxDDR0.r0",
 
2788
    /* pszDescription */
 
2789
    "ICH9 PCI to PCI bridge",
 
2790
    /* fFlags */
 
2791
    PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
 
2792
    /* fClass */
 
2793
    PDM_DEVREG_CLASS_BUS_PCI,
 
2794
    /* cMaxInstances */
 
2795
    ~0,
 
2796
    /* cbInstance */
 
2797
    sizeof(PCIBUS),
 
2798
    /* pfnConstruct */
 
2799
    ich9pcibridgeConstruct,
 
2800
    /* pfnDestruct */
 
2801
    NULL,
 
2802
    /* pfnRelocate */
 
2803
    ich9pcibridgeRelocate,
 
2804
    /* pfnIOCtl */
 
2805
    NULL,
 
2806
    /* pfnPowerOn */
 
2807
    NULL,
 
2808
    /* pfnReset */
 
2809
    NULL, /* Must be NULL, to make sure only bus driver handles reset */
 
2810
    /* pfnSuspend */
 
2811
    NULL,
 
2812
    /* pfnResume */
 
2813
    NULL,
 
2814
    /* pfnAttach */
 
2815
    NULL,
 
2816
    /* pfnDetach */
 
2817
    NULL,
 
2818
    /* pfnQueryInterface */
 
2819
    NULL,
 
2820
    /* pfnInitComplete */
 
2821
    NULL,
 
2822
    /* pfnPowerOff */
 
2823
    NULL,
 
2824
    /* pfnSoftReset */
 
2825
    NULL,
 
2826
    /* u32VersionEnd */
 
2827
    PDM_DEVREG_VERSION
 
2828
};
 
2829
 
 
2830
#endif /* IN_RING3 */
 
2831
#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */