1
/* $Id: DevPciIch9.cpp 35397 2011-01-03 23:11:50Z vboxsync $ */
3
* DevPCI - ICH9 southbridge PCI bus emulation Device.
7
* Copyright (C) 2010 Oracle Corporation
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.
18
/*******************************************************************************
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
26
#include <VBox/vmm/pdmdev.h>
28
#include <iprt/assert.h>
29
#include <iprt/string.h>
31
#include <iprt/alloc.h>
36
#include "MsiCommon.h"
45
/** Number of bridges attached to the bus. */
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;
53
/** R3 pointer to the device instance. */
54
PPDMDEVINSR3 pDevInsR3;
55
/** Pointer to the PCI R3 helpers. */
56
PCPDMPCIHLPR3 pPciHlpR3;
58
/** R0 pointer to the device instance. */
59
PPDMDEVINSR0 pDevInsR0;
60
/** Pointer to the PCI R0 helpers. */
61
PCPDMPCIHLPR0 pPciHlpR0;
63
/** RC pointer to the device instance. */
64
PPDMDEVINSRC pDevInsRC;
65
/** Pointer to the PCI RC helpers. */
66
PCPDMPCIHLPRC pPciHlpRC;
68
/** The PCI device for the PCI bridge. */
74
/** @def PCI_APIC_IRQ_PINS
75
* Number of pins for interrupts if the APIC is used.
77
#define PCI_APIC_IRQ_PINS 8
80
* PCI Globals - This is the host-to-pci bridge and the root bus.
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;
91
#if HC_ARCH_BITS == 64
95
/** PCI bus which is attached to the host-to-PCI bridge. */
99
/** I/O APIC irq levels */
100
volatile uint32_t uaPciApicIrqLevels[PCI_APIC_IRQ_PINS];
102
#if 1 /* Will be moved into the BIOS soon. */
103
/** The next I/O port address which the PCI BIOS will use. */
105
/** The next MMIO address which the PCI BIOS will use. */
106
uint32_t uPciBiosMmio;
107
/** Actual bus number. */
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;
116
/** Config register. */
118
} PCIGLOBALS, *PPCIGLOBALS;
127
/*******************************************************************************
128
* Defined Constants And Macros *
129
*******************************************************************************/
131
/** @def VBOX_ICH9PCI_SAVED_STATE_VERSION
132
* Saved state version of the ICH9 PCI bus device.
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
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.
146
#define PCIROOTBUS_2_PCIGLOBALS(pPciBus) ( (PPCIGLOBALS)((uintptr_t)(pPciBus) - RT_OFFSETOF(PCIGLOBALS, aPciBus)) )
150
* Acquires the PDM lock. This is a NOP if locking is disabled. */
152
* Releases the PDM lock. This is a NOP if locking is disabled. */
153
#define PCI_LOCK(pDevIns, rc) \
155
int rc2 = DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \
156
if (rc2 != VINF_SUCCESS) \
159
#define PCI_UNLOCK(pDevIns) \
160
DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns)
162
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
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);
178
static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel);
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);
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)
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
197
DECLINLINE(void) ich9pciStateToPciAddr(PPCIGLOBALS pGlobals, RTGCPHYS addr, PciAddress* pPciAddr)
199
pPciAddr->iBus = (pGlobals->uConfigReg >> 16) & 0xff;
200
pPciAddr->iDeviceFunc = (pGlobals->uConfigReg >> 8) & 0xff;
201
pPciAddr->iRegister = (pGlobals->uConfigReg & 0xfc) | (addr & 3);
204
PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
206
ich9pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), pPciDev->devfn, pPciDev, iIrq, iLevel);
209
PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
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.
218
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
219
PPCIDEVICE pPciDevBus = pPciDev;
220
int iIrqPinBridge = iIrq;
221
uint8_t uDevFnBridge = 0;
223
/* Walk the chain until we reach the host bus. */
226
uDevFnBridge = pBus->aPciDev.devfn;
227
iIrqPinBridge = ((pPciDevBus->devfn >> 3) + iIrqPinBridge) & 3;
229
/* Get the parent. */
230
pBus = pBus->aPciDev.Int.s.CTX_SUFF(pBus);
231
pPciDevBus = &pBus->aPciDev;
232
} while (pBus->iBus != 0);
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);
239
* Port I/O Handler for PCI address OUT operations.
241
* @returns VBox status code.
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.
249
PDMBOTHCBDECL(int) ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
251
Log(("ich9pciIOPortAddressWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
255
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
257
PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
258
pThis->uConfigReg = u32 & ~3; /* Bits 0-1 are reserved and we silently clear them */
266
* Port I/O Handler for PCI address IN operations.
268
* @returns VBox status code.
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.
276
PDMBOTHCBDECL(int) ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
281
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
282
PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
283
*pu32 = pThis->uConfigReg;
285
Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32));
289
Log(("ich9pciIOPortAddressRead: Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", Port, cb));
291
return VERR_IOM_IOPORT_UNUSED;
294
static int ich9pciDataWriteAddr(PPCIGLOBALS pGlobals, PciAddress* pAddr,
295
uint32_t val, int cb, int rcReschedule)
297
int rc = VINF_SUCCESS;
299
if (pAddr->iRegister > 0xff)
301
LogRel(("PCI: attempt to write extended register: %x (%d) <- val\n", pAddr->iRegister, cb, val));
305
if (pAddr->iBus != 0)
307
if (pGlobals->aPciBus.cBridges)
309
#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
310
PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pAddr->iBus);
313
AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
314
pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, pAddr->iBus, pAddr->iDeviceFunc, pAddr->iRegister, val, cb);
318
// do nothing, bridge not found
328
if (pGlobals->aPciBus.apDevices[pAddr->iDeviceFunc])
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);
342
Log2(("ich9pciDataWriteAddr: %02x:%02x:%02x reg %x(%d) %x %Rrc\n",
343
pAddr->iBus, pAddr->iDeviceFunc >> 3, pAddr->iDeviceFunc & 0x7, pAddr->iRegister,
349
static int ich9pciDataWrite(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len)
353
LogFlow(("ich9pciDataWrite: config=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len));
355
if (!(pGlobals->uConfigReg & (1 << 31)))
358
if ((pGlobals->uConfigReg & 0x3) != 0)
361
/* Compute destination device */
362
ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
364
return ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VINF_IOM_HC_IOPORT_WRITE);
367
static void ich9pciNoMem(void* ptr, int cb)
369
for (int i = 0; i < cb; i++)
370
((uint8_t*)ptr)[i] = 0xff;
374
* Port I/O Handler for PCI data OUT operations.
376
* @returns VBox status code.
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.
384
PDMBOTHCBDECL(int) ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
386
Log(("pciIOPortDataWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
388
int rc = VINF_SUCCESS;
391
PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
392
rc = ich9pciDataWrite(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32, cb);
396
AssertMsgFailed(("Unaligned write to port %#x u32=%#x cb=%d\n", Port, u32, cb));
400
static int ich9pciDataReadAddr(PPCIGLOBALS pGlobals, PciAddress* pPciAddr, int cb,
401
uint32_t *pu32, int rcReschedule)
403
int rc = VINF_SUCCESS;
405
if (pPciAddr->iRegister > 0xff)
407
LogRel(("PCI: attempt to read extended register: %x\n", pPciAddr->iRegister));
408
ich9pciNoMem(pu32, cb);
413
if (pPciAddr->iBus != 0)
415
if (pGlobals->aPciBus.cBridges)
417
#ifdef IN_RING3 /** @todo do lookup in R0/RC too! */
418
PPCIDEVICE pBridgeDevice = ich9pciFindBridge(&pGlobals->aPciBus, pPciAddr->iBus);
421
AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
422
*pu32 = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, pPciAddr->iBus, pPciAddr->iDeviceFunc, pPciAddr->iRegister, cb);
425
ich9pciNoMem(pu32, cb);
431
ich9pciNoMem(pu32, cb);
435
if (pGlobals->aPciBus.apDevices[pPciAddr->iDeviceFunc])
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));
447
ich9pciNoMem(pu32, cb);
451
Log2(("ich9pciDataReadAddr: %02x:%02x:%02x reg %x(%d) gave %x %Rrc\n",
452
pPciAddr->iBus, pPciAddr->iDeviceFunc >> 3, pPciAddr->iDeviceFunc & 0x7, pPciAddr->iRegister,
458
static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int cb, uint32_t *pu32)
462
LogFlow(("ich9pciDataRead: config=%x cb=%d\n", pGlobals->uConfigReg, cb));
466
if (!(pGlobals->uConfigReg & (1 << 31)))
469
if ((pGlobals->uConfigReg & 0x3) != 0)
472
/* Compute destination device */
473
ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
475
return ich9pciDataReadAddr(pGlobals, &aPciAddr, cb, pu32, VINF_IOM_HC_IOPORT_READ);
479
* Port I/O Handler for PCI data IN operations.
481
* @returns VBox status code.
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.
489
PDMBOTHCBDECL(int) ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
494
PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
495
int rc = ich9pciDataRead(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, cb, pu32);
497
Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x (%Rrc)\n", Port, cb, *pu32, rc));
500
AssertMsgFailed(("Unaligned read from port %#x cb=%d\n", Port, cb));
501
return VERR_IOM_IOPORT_UNUSED;
504
/* Compute mapping of PCI slot and IRQ number to APIC interrupt line */
505
DECLINLINE(int) ich9pciSlot2ApicIrq(uint8_t uSlot, int irq_num)
507
return (irq_num + uSlot) & 7;
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)
515
int iSlotAddend = (uDevFn >> 3) - 1;
516
return (iIrqNum + iSlotAddend) & 3;
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 };
522
/* Add one more level up request on APIC input line */
523
DECLINLINE(void) ich9pciApicLevelUp(PPCIGLOBALS pGlobals, int irq_num)
525
ASMAtomicIncU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
528
/* Remove one level up request on APIC input line */
529
DECLINLINE(void) ich9pciApicLevelDown(PPCIGLOBALS pGlobals, int irq_num)
531
ASMAtomicDecU32(&pGlobals->uaPciApicIrqLevels[irq_num]);
534
static void ich9pciApicSetIrq(PPCIBUS pBus, uint8_t uDevFn, PCIDevice *pPciDev, int irq_num1, int iLevel, int iForcedIrq)
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));
539
if (iForcedIrq == -1)
541
int apic_irq, apic_level;
542
PPCIGLOBALS pGlobals = PCIROOTBUS_2_PCIGLOBALS(pBus);
543
int irq_num = ich9pciSlot2ApicIrq(uDevFn >> 3, irq_num1);
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);
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);
556
if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
559
* we raised it few lines above, as PDM_IRQ_LEVEL_FLIP_FLOP has
560
* PDM_IRQ_LEVEL_HIGH bit set
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);
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);
576
static void ich9pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel)
579
if (PCIDevIsIntxDisabled(pPciDev))
581
if (MsiIsEnabled(pPciDev))
583
PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
584
MsiNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
587
if (MsixIsEnabled(pPciDev))
589
PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
590
MsixNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
595
PPCIBUS pBus = &pGlobals->aPciBus;
596
const bool fIsAcpiDevice = PCIDevGetDeviceId(pPciDev) == 0x7113;
598
/* Check if the state changed. */
599
if (pPciDev->Int.s.uIrqPinState != iLevel)
601
pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
603
/* Send interrupt to I/O APIC only now. */
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).
612
ich9pciApicSetIrq(pBus, uDevFn, pPciDev, -1, iLevel, PCIDevGetInterruptLine(pPciDev));
614
ich9pciApicSetIrq(pBus, uDevFn, pPciDev, iIrq, iLevel, -1);
618
PDMBOTHCBDECL(int) ich9pciMcfgMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
620
PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
624
Log2(("ich9pciMcfgMMIOWrite: %RGp(%d) \n", GCPhysAddr, cb));
626
PCI_LOCK(pDevIns, VINF_IOM_HC_MMIO_WRITE);
628
ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest);
636
u32 = *(uint16_t*)pv;
639
u32 = *(uint32_t*)pv;
645
int rc = ich9pciDataWriteAddr(pGlobals, &aDest, u32, cb, VINF_IOM_HC_MMIO_WRITE);
651
PDMBOTHCBDECL(int) ich9pciMcfgMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
653
PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
657
LogFlow(("ich9pciMcfgMMIORead: %RGp(%d) \n", GCPhysAddr, cb));
659
PCI_LOCK(pDevIns, VINF_IOM_HC_MMIO_READ);
661
ich9pciPhysToPciAddr(pGlobals, GCPhysAddr, &aDest);
663
int rc = ich9pciDataReadAddr(pGlobals, &aDest, cb, &rv, VINF_IOM_HC_MMIO_READ);
670
*(uint8_t*)pv = (uint8_t)rv;
673
*(uint16_t*)pv = (uint16_t)rv;
676
*(uint32_t*)pv = (uint32_t)rv;
690
DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus)
692
/* Search for a fitting bridge. */
693
for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
696
* Examine secondary and subordinate bus number.
697
* If the target bus is in the range we pass the request on to the bridge.
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"));
703
if ( iBus >= PCIDevGetByte(pBridgeTemp, VBOX_PCI_SECONDARY_BUS)
704
&& iBus <= PCIDevGetByte(pBridgeTemp, VBOX_PCI_SUBORDINATE_BUS))
712
DECLINLINE(uint32_t) ich9pciGetRegionReg(int iRegion)
714
return (iRegion == VBOX_PCI_ROM_SLOT) ?
715
VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
718
#define INVALID_PCI_ADDRESS ~0U
720
static int ich9pciUnmapRegion(PPCIDEVICE pDev, int iRegion)
722
PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
723
int rc = VINF_SUCCESS;
724
PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
726
Assert (pRegion->size != 0);
728
if (pRegion->addr != INVALID_PCI_ADDRESS)
730
if (pRegion->type & PCI_ADDRESS_SPACE_IO)
733
rc = PDMDevHlpIOPortDeregister(pDev->pDevIns, pRegion->addr, pRegion->size);
738
RTGCPHYS GCPhysBase = pRegion->addr;
739
if (pBus->pPciHlpR3->pfnIsMMIO2Base(pBus->pDevInsR3, pDev->pDevIns, GCPhysBase))
742
rc = pRegion->map_func(pDev, iRegion, NIL_RTGCPHYS, pRegion->size, (PCIADDRESSSPACE)(pRegion->type));
744
rc = PDMDevHlpMMIO2Unmap(pDev->pDevIns, iRegion, GCPhysBase);
747
rc = PDMDevHlpMMIODeregister(pDev->pDevIns, GCPhysBase, pRegion->size);
750
pRegion->addr = INVALID_PCI_ADDRESS;
756
static void ich9pciUpdateMappings(PCIDevice* pDev)
758
PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
759
uint32_t uLast, uNew;
761
int iCmd = PCIDevGetCommand(pDev);
762
for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
764
PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
765
uint32_t uConfigReg = ich9pciGetRegionReg(iRegion);
766
int32_t iRegionSize = pRegion->size;
769
if (iRegionSize == 0)
772
AssertMsg((pRegion->type & PCI_ADDRESS_SPACE_BAR64) == 0, ("64-bit BARs not yet implemented\n"));
774
if (pRegion->type & PCI_ADDRESS_SPACE_IO)
777
if (iCmd & PCI_COMMAND_IOACCESS)
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;
787
uNew = INVALID_PCI_ADDRESS;
792
if (iCmd & PCI_COMMAND_MEMACCESS)
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;
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
806
if (uLast <= uNew || uNew == 0 || uLast == INVALID_PCI_ADDRESS)
807
uNew = INVALID_PCI_ADDRESS;
810
uNew = INVALID_PCI_ADDRESS;
812
/* now do the real mapping */
813
if (uNew != pRegion->addr)
815
if (pRegion->addr != INVALID_PCI_ADDRESS)
816
ich9pciUnmapRegion(pDev, iRegion);
818
pRegion->addr = uNew;
819
if (pRegion->addr != INVALID_PCI_ADDRESS)
821
/* finally, map the region */
822
rc = pRegion->map_func(pDev, iRegion,
823
pRegion->addr, pRegion->size,
824
(PCIADDRESSSPACE)(pRegion->type));
831
static DECLCALLBACK(int) ich9pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
833
PPCIBUS pBus = DEVINS_2_PCIBUS(pDevIns);
840
|| iDev >= (int)RT_ELEMENTS(pBus->apDevices)
843
AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
844
return VERR_INVALID_PARAMETER;
848
* Register the device.
850
return ich9pciRegisterInternal(pBus, iDev, pPciDev, pszName);
854
static DECLCALLBACK(int) ich9pciRegisterMsi(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PPDMMSIREG pMsiReg)
858
rc = MsiInit(pPciDev, pMsiReg);
859
if (rc != VINF_SUCCESS)
862
rc = MsixInit(pPciDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp), pPciDev, pMsiReg);
863
if (rc != VINF_SUCCESS)
870
static DECLCALLBACK(int) ich9pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
873
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
880
|| iDev >= (int)RT_ELEMENTS(pBus->apDevices))
882
AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
883
return VERR_INVALID_PARAMETER;
887
* Register the device.
889
return ich9pciRegisterInternal(pBus, iDev, pPciDev, pszName);
892
static DECLCALLBACK(int) ich9pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
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);
912
* Register the I/O region.
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;
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);
929
static DECLCALLBACK(void) ich9pciSetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
930
PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
933
*ppfnReadOld = pPciDev->Int.s.pfnConfigRead;
934
pPciDev->Int.s.pfnConfigRead = pfnRead;
937
*ppfnWriteOld = pPciDev->Int.s.pfnConfigWrite;
938
pPciDev->Int.s.pfnConfigWrite = pfnWrite;
942
* Saves a state of the PCI device.
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.
949
static DECLCALLBACK(int) ich9pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
951
return SSMR3PutMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
954
static int ich9pciR3CommonSaveExec(PPCIBUS pBus, PSSMHANDLE pSSM)
957
* Iterate thru all the devices.
959
for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
961
PPCIDEVICE pDev = pBus->apDevices[i];
964
/* Device position */
965
SSMR3PutU32(pSSM, i);
966
/* PCI config registers */
967
SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config));
970
int rc = SSMR3PutU32(pSSM, pDev->Int.s.uFlags);
975
rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
980
rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapOffset);
983
rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsiCapSize);
988
rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapOffset);
991
rc = SSMR3PutU8(pSSM, pDev->Int.s.u8MsixCapSize);
994
/* Save MSI-X page state */
995
if (pDev->Int.s.u8MsixCapOffset != 0)
997
Assert(pDev->Int.s.pMsixPageR3 != NULL);
998
SSMR3PutMem(pSSM, pDev->Int.s.pMsixPageR3, 0x1000);
1004
return SSMR3PutU32(pSSM, UINT32_MAX); /* terminator */
1007
static DECLCALLBACK(int) ich9pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1009
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1014
SSMR3PutU32(pSSM, pThis->uConfigReg);
1019
for (int i = 0; i < PCI_APIC_IRQ_PINS; i++)
1020
SSMR3PutU32(pSSM, pThis->uaPciApicIrqLevels[i]);
1022
SSMR3PutU32(pSSM, ~0); /* separator */
1024
return ich9pciR3CommonSaveExec(&pThis->aPciBus, pSSM);
1028
static DECLCALLBACK(int) ich9pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1030
PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
1031
return ich9pciR3CommonSaveExec(pThis, pSSM);
1035
static void ich9pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb)
1037
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
1039
LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, u32Value, cb));
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))
1044
PPCIDEVICE pBridgeDevice = ich9pciFindBridge(pBus, iBus);
1047
AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
1048
pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb);
1053
/* This is the target bus, pass the write to the device. */
1054
PPCIDEVICE pPciDev = pBus->apDevices[iDevice];
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);
1063
static uint32_t ich9pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb)
1065
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
1068
LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, cb));
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))
1073
PPCIDEVICE pBridgeDevice = ich9pciFindBridge(pBus, iBus);
1076
AssertPtr( pBridgeDevice->Int.s.pfnBridgeConfigRead);
1077
u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb);
1080
ich9pciNoMem(&u32Value, 4);
1084
/* This is the target bus, pass the read to the device. */
1085
PPCIDEVICE pPciDev = pBus->apDevices[iDevice];
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));
1092
ich9pciNoMem(&u32Value, 4);
1100
* Common routine for restoring the config registers of a PCI device.
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.
1106
static void pciR3CommonRestoreConfig(PPCIDEVICE pDev, uint8_t const *pbSrcConfig, bool fIsBridge)
1109
* This table defines the fields for normal devices and bridge devices, and
1110
* the order in which they need to be restored.
1112
static const struct PciField
1118
const char *pszName;
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" },
1173
/* Check that we've got full register coverage. */
1174
uint32_t bmDevice[0x40 / 32];
1175
uint32_t bmBridge[0x40 / 32];
1178
for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
1180
uint8_t off = s_aFields[i].off;
1181
uint8_t cb = s_aFields[i].cb;
1182
uint8_t f = s_aFields[i].fBridge;
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);
1192
for (uint32_t off = 0; off < 0x40; off++)
1194
AssertMsg(ASMBitTest(bmDevice, off), ("%#x\n", off));
1195
AssertMsg(ASMBitTest(bmBridge, off), ("%#x\n", off));
1200
* Loop thru the fields covering the 64 bytes of standard registers.
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)
1207
uint8_t const off = s_aFields[i].off;
1208
uint8_t const cb = s_aFields[i].cb;
1214
u32Src = pbSrcConfig[off];
1215
u32Dst = pbDstConfig[off];
1218
u32Src = *(uint16_t const *)&pbSrcConfig[off];
1219
u32Dst = *(uint16_t const *)&pbDstConfig[off];
1222
u32Src = *(uint32_t const *)&pbSrcConfig[off];
1223
u32Dst = *(uint32_t const *)&pbDstConfig[off];
1230
if ( u32Src != u32Dst
1231
|| off == VBOX_PCI_COMMAND)
1233
if (u32Src != u32Dst)
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));
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));
1242
if (off == VBOX_PCI_COMMAND)
1243
PCIDevSetCommand(pDev, 0); /* For remapping, see ich9pciR3CommonLoadExec. */
1244
pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb);
1249
* The device dependent registers.
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.
1255
for (uint32_t off = 0x40; off < sizeof(pDev->config); off++)
1256
if (pbDstConfig[off] != pbSrcConfig[off])
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];
1265
* Common worker for ich9pciR3LoadExec and ich9pcibridgeR3LoadExec.
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.
1273
static DECLCALLBACK(int) ich9pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1279
Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
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.
1286
* The register value is restored afterwards so we can do proper
1287
* LogRels in pciR3CommonRestoreConfig.
1289
for (i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
1291
PPCIDEVICE pDev = pBus->apDevices[i];
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);
1301
void* pvMsixPage = RTMemTmpAllocZ(0x1000);
1303
* Iterate all the devices.
1310
/* index / terminator */
1311
rc = SSMR3GetU32(pSSM, &u32);
1314
if (u32 == (uint32_t)~0)
1316
if ( u32 >= RT_ELEMENTS(pBus->apDevices)
1319
AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
1323
/* skip forward to the device checking that no new devices are present. */
1324
for (; i < u32; i++)
1326
pDev = pBus->apDevices[i];
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));
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));
1346
rc = SSMR3GetU32(pSSM, &DevTmp.Int.s.uFlags);
1350
rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
1354
rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapOffset);
1358
rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsiCapSize);
1362
rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapOffset);
1366
rc = SSMR3GetU8(pSSM, &DevTmp.Int.s.u8MsixCapSize);
1370
/* Load MSI-X page state */
1371
if (DevTmp.Int.s.u8MsixCapOffset != 0)
1373
Assert(pvMsixPage != NULL);
1374
SSMR3GetMem(pSSM, pvMsixPage, 0x1000);
1379
/* check that it's still around. */
1380
pDev = pBus->apDevices[i];
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));
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));
1396
/* commit the loaded device config. */
1397
pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
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)
1406
Assert(pDev->Int.s.pMsixPageR3 != NULL);
1407
memcpy(pDev->Int.s.pMsixPageR3, pvMsixPage, 0x1000);
1413
RTMemTmpFree(pvMsixPage);
1419
* Loads a saved PCI device state.
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.
1426
static DECLCALLBACK(int) ich9pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
1428
return SSMR3GetMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
1431
static DECLCALLBACK(int) ich9pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1433
PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1434
PPCIBUS pBus = &pThis->aPciBus;
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;
1447
SSMR3GetU32(pSSM, &pThis->uConfigReg);
1452
for (int i = 0; i < PCI_APIC_IRQ_PINS; i++)
1453
SSMR3GetU32(pSSM, (uint32_t*)&pThis->uaPciApicIrqLevels[i]);
1456
rc = SSMR3GetU32(pSSM, &u32);
1459
if (u32 != (uint32_t)~0)
1460
AssertMsgFailedReturn(("u32=%#x\n", u32), rc);
1462
return ich9pciR3CommonLoadExec(pBus, pSSM, uVersion, uPass);
1465
static DECLCALLBACK(int) ich9pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
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);
1473
static uint32_t ich9pciConfigRead(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t len)
1475
/* Will only work in LSB case */
1477
PciAddress aPciAddr;
1479
aPciAddr.iBus = uBus;
1480
aPciAddr.iDeviceFunc = uDevFn;
1481
aPciAddr.iRegister = addr;
1483
/* cannot be rescheduled, as already in R3 */
1484
int rc = ich9pciDataReadAddr(pGlobals, &aPciAddr, len, &u32Val, VERR_INTERNAL_ERROR);
1489
static void ich9pciConfigWrite(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val, uint32_t len)
1491
PciAddress aPciAddr;
1493
aPciAddr.iBus = uBus;
1494
aPciAddr.iDeviceFunc = uDevFn;
1495
aPciAddr.iRegister = addr;
1497
/* cannot be rescheduled, as already in R3 */
1498
int rc = ich9pciDataWriteAddr(pGlobals, &aPciAddr, val, len, VERR_INTERNAL_ERROR);
1502
static void ich9pciSetRegionAddress(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, int iRegion, uint32_t addr)
1504
uint32_t uReg = ich9pciGetRegionReg(iRegion);
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);
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. */
1518
/* Write address of the device. */
1519
ich9pciConfigWrite(pGlobals, uBus, uDevFn, uReg, addr, 4);
1521
/* enable memory mappings */
1522
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_COMMAND, uCmd, 2);
1526
static void ich9pciBiosInitBridge(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
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);
1532
/* Add position of this bridge into the array. */
1533
paBridgePositions[cBridgeDepth+1] = (uDevFn >> 3);
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.
1540
if ((pGlobals->uPciBiosIo % 4096) != 0)
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));
1545
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_BASE, (pGlobals->uPciBiosIo >> 8) & 0xf0, 1);
1547
/* The MMIO range for the bridge must be aligned to a 1MB boundary. */
1548
if ((pGlobals->uPciBiosMmio % (1024 * 1024)) != 0)
1550
pGlobals->uPciBiosMmio = RT_ALIGN_32(pGlobals->uPciBiosMmio, 1024*1024);
1551
Log(("%s: Aligned MMIO start address. New address %#x\n", __FUNCTION__, pGlobals->uPciBiosMmio));
1553
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_BASE, (pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xffff0), 2);
1555
/* Save values to compare later to. */
1556
uint32_t u32IoAddressBase = pGlobals->uPciBiosIo;
1557
uint32_t u32MMIOAddressBase = pGlobals->uPciBiosMmio;
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);
1563
/* The number of bridges behind the this one is now available. */
1564
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, pGlobals->uBus, 1);
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.
1572
if ((u32IoAddressBase != pGlobals->uPciBiosIo) && ((pGlobals->uPciBiosIo % 4096) != 0))
1574
/* The upper boundary must be one byte less than a 4KB boundary. */
1575
pGlobals->uPciBiosIo = RT_ALIGN_32(pGlobals->uPciBiosIo, 4*1024);
1578
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->uPciBiosIo >> 8) & 0xf0) - 1, 1);
1580
/* Same with the MMIO limit register but with 1MB boundary here. */
1581
if ((u32MMIOAddressBase != pGlobals->uPciBiosMmio) && ((pGlobals->uPciBiosMmio % (1024 * 1024)) != 0))
1583
/* The upper boundary must be one byte less than a 1MB boundary. */
1584
pGlobals->uPciBiosMmio = RT_ALIGN_32(pGlobals->uPciBiosMmio, 1024*1024);
1586
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->uPciBiosMmio >> 16) & UINT32_C(0xfff0)) - 1, 2);
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.
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);
1599
static void ich9pciBiosInitDevice(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions)
1602
uint16_t uDevClass, uVendor, uDevice;
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);
1609
/* If device is present */
1610
if (uVendor == 0xffff)
1616
/* IDE controller */
1617
ich9pciConfigWrite(pGlobals, uBus, uDevFn, 0x40, 0x8000, 2); /* enable IDE0 */
1618
ich9pciConfigWrite(pGlobals, uBus, uDevFn, 0x42, 0x8000, 2); /* enable IDE1 */
1622
/* VGA controller */
1623
if (uVendor != 0x80ee)
1625
/* VGA: map frame buffer to default Bochs VBE address */
1626
ich9pciSetRegionAddress(pGlobals, uBus, uDevFn, 0, 0xE0000000);
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.
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,
1639
/* PCI-to-PCI bridge. */
1640
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_PRIMARY_BUS, uBus, 1);
1642
AssertMsg(pGlobals->uBus < 255, ("Too many bridges on the bus\n"));
1644
ich9pciBiosInitBridge(pGlobals, uBus, uDevFn, cBridgeDepth, paBridgePositions);
1649
/* default memory mappings */
1651
* We ignore ROM region here.
1653
for (int iRegion = 0; iRegion < (PCI_NUM_REGIONS-1); iRegion++)
1655
uint32_t u32Address = ich9pciGetRegionReg(iRegion);
1657
/* Calculate size - we write all 1s into the BAR, and then evaluate which bits
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 */
1668
bool fIsPio = ((u8ResourceType & PCI_COMMAND_IOACCESS) == PCI_COMMAND_IOACCESS);
1670
* Invert all bits and add 1 to get size of the region.
1671
* (From PCI implementation note)
1673
if (fIsPio && (u32Size & UINT32_C(0xffff0000)) == 0)
1674
u32Size = (~(u32Size | UINT32_C(0xffff0000))) + 1;
1676
u32Size = (~u32Size) + 1;
1678
Log(("%s: Size of region %u for device %d on bus %d is %u\n", __FUNCTION__, iRegion, uDevFn, uBus, u32Size));
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);
1687
Log(("%s: New address is %#x\n", __FUNCTION__, *paddr));
1694
/* map the interrupt */
1695
uint32_t iPin = ich9pciConfigRead(pGlobals, uBus, uDevFn, VBOX_PCI_INTERRUPT_PIN, 1);
1698
uint8_t uBridgeDevFn = uDevFn;
1701
/* We need to go up to the host bus to see which irq this device will assert there. */
1702
while (cBridgeDepth != 0)
1704
/* Get the pin the device would assert on the bridge. */
1705
iPin = ((uBridgeDevFn >> 3) + iPin) & 3;
1706
uBridgeDevFn = paBridgePositions[cBridgeDepth];
1710
int iIrq = aPciIrqs[ich9pciSlotGetPirq(uBus, uDevFn, iPin)];
1711
ich9pciConfigWrite(pGlobals, uBus, uDevFn, VBOX_PCI_INTERRUPT_LINE, iIrq, 1);
1715
static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
1718
uint8_t elcr[2] = {0, 0};
1719
PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
1720
PVM pVM = PDMDevHlpGetVM(pDevIns);
1724
* Set the start addresses.
1726
pGlobals->uPciBiosIo = 0xd000;
1727
pGlobals->uPciBiosMmio = UINT32_C(0xf0000000);
1733
for (i = 0; i < 256; i++)
1735
uint8_t aBridgePositions[256];
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);
1743
return VINF_SUCCESS;
1746
static DECLCALLBACK(uint32_t) ich9pciConfigReadDev(PCIDevice *aDev, uint32_t u32Address, unsigned len)
1748
if ((u32Address + len) > 256 && (u32Address + len) < 4096)
1750
AssertMsgReturn(false, ("Read from extended registers falled back to generic code\n"), 0);
1753
if ( PCIIsMsiCapable(aDev)
1754
&& (u32Address >= aDev->Int.s.u8MsiCapOffset)
1755
&& (u32Address < aDev->Int.s.u8MsiCapOffset + aDev->Int.s.u8MsiCapSize)
1758
return MsiPciConfigRead(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), aDev, u32Address, len);
1761
if ( PCIIsMsixCapable(aDev)
1762
&& (u32Address >= aDev->Int.s.u8MsixCapOffset)
1763
&& (u32Address < aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
1766
return MsixPciConfigRead(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), aDev, u32Address, len);
1769
AssertMsgReturn(u32Address + len <= 256, ("Read after end of PCI config space\n"),
1774
return PCIDevGetByte(aDev, u32Address);
1776
return PCIDevGetWord(aDev, u32Address);
1778
return PCIDevGetDWord(aDev, u32Address);
1785
DECLINLINE(void) ich9pciWriteBarByte(PCIDevice *aDev, int iRegion, int iOffset, uint8_t u8Val)
1787
PCIIORegion * pRegion = &aDev->Int.s.aIORegions[iRegion];
1789
int iRegionSize = pRegion->size;
1791
Log3(("ich9pciWriteBarByte: region=%d off=%d val=%x size=%d\n",
1792
iRegion, iOffset, u8Val, iRegionSize));
1794
/* Region doesn't exist */
1795
if (iRegionSize == 0)
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;
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 */;
1811
uint8_t u8Old = PCIDevGetByte(aDev, uAddr) & uMask;
1812
u8Val = (u8Old & uMask) | (u8Val & ~uMask);
1814
Log3(("ich9pciWriteBarByte: was %x writing %x\n", u8Old, u8Val));
1816
PCIDevSetByte(aDev, uAddr, u8Val);
1819
* See paragraph 7.5 of PCI Express specification (p. 349) for definition of
1820
* registers and their writability policy.
1822
static DECLCALLBACK(void) ich9pciConfigWriteDev(PCIDevice *aDev, uint32_t u32Address,
1823
uint32_t val, unsigned len)
1827
if ((u32Address + len) > 256 && (u32Address + len) < 4096)
1829
AssertMsgReturnVoid(false, ("Write to extended registers falled back to generic code\n"));
1832
AssertMsgReturnVoid(u32Address + len <= 256, ("Write after end of PCI config space\n"));
1834
if ( PCIIsMsiCapable(aDev)
1835
&& (u32Address >= aDev->Int.s.u8MsiCapOffset)
1836
&& (u32Address < aDev->Int.s.u8MsiCapOffset + aDev->Int.s.u8MsiCapSize)
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);
1845
if ( PCIIsMsixCapable(aDev)
1846
&& (u32Address >= aDev->Int.s.u8MsixCapOffset)
1847
&& (u32Address < aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
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);
1856
uint32_t addr = u32Address;
1857
bool fUpdateMappings = false;
1858
bool fP2PBridge = false;
1859
for (uint32_t i = 0; i < len; i++)
1861
bool fWritable = false;
1863
switch (PCIDevGetHeaderType(aDev))
1865
case 0x00: /* normal device */
1866
case 0x80: /* multi-function device */
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:
1884
/* Others can be written */
1890
case 0x01: /* PCI-PCI bridge */
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:
1912
AssertMsgFailed(("Unknown header type %x\n", PCIDevGetHeaderType(aDev)));
1917
uint8_t u8Val = (uint8_t)val;
1920
case VBOX_PCI_COMMAND: /* Command register, bits 0-7. */
1921
fUpdateMappings = true;
1922
PCIDevSetByte(aDev, addr, u8Val);
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);
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;
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;
1942
case VBOX_PCI_ROM_ADDRESS: case VBOX_PCI_ROM_ADDRESS +1: case VBOX_PCI_ROM_ADDRESS +2: case VBOX_PCI_ROM_ADDRESS +3:
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:
1951
/* We check that, as same PCI register numbers as BARs may mean different registers for bridges */
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;
1966
PCIDevSetByte(aDev, addr, u8Val);
1972
if (fUpdateMappings)
1973
/* if the command/base address register is modified, we must modify the mappings */
1974
ich9pciUpdateMappings(aDev);
1977
/* Slot/functions assignment per table at p. 12 of ICH9 family spec update */
1978
static const struct {
1979
const char* pszName;
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. */
1986
"i82801", 30, 0 /* Host Controller */
1990
static bool assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName, int iDevFn, PciAddress* aPosition)
1992
aPosition->iBus = 0;
1993
aPosition->iDeviceFunc = iDevFn;
1994
aPosition->iRegister = 0; /* N/A */
1996
/* Hardcoded slots/functions, per chipset spec */
1997
for (size_t i = 0; i < RT_ELEMENTS(PciSlotAssignments); i++)
1999
if (!strcmp(pszName, PciSlotAssignments[i].pszName))
2001
PCISetRequestedDevfunc(pPciDev);
2002
aPosition->iDeviceFunc =
2003
(PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
2008
/* Explicit slot request */
2009
if (iDevFn >=0 && iDevFn < (int)RT_ELEMENTS(pBus->apDevices))
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)
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])
2026
PCIClearRequestedDevfunc(pPciDev);
2027
aPosition->iDeviceFunc = iPos;
2035
static bool hasHardAssignedDevsInSlot(PPCIBUS pBus, int iSlot)
2037
PCIDevice** aSlot = &pBus->apDevices[iSlot << 3];
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]))
2050
static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
2052
PciAddress aPosition = {0, 0, 0};
2055
* Find device position
2057
if (!assignPosition(pBus, pPciDev, pszName, iDev, &aPosition))
2059
AssertMsgFailed(("Couldn't asssign position!\n"));
2060
return VERR_PDM_TOO_PCI_MANY_DEVICES;
2063
AssertMsgReturn(aPosition.iBus == 0,
2064
("Assigning behind the bridge not implemented yet\n"),
2065
VERR_PDM_TOO_PCI_MANY_DEVICES);
2068
iDev = aPosition.iDeviceFunc;
2070
* Check if we can really take this slot, possibly by relocating
2071
* its current habitant, if it wasn't hard assigned too.
2073
if (PCIIsRequestedDevfunc(pPciDev) &&
2074
pBus->apDevices[iDev] &&
2075
PCIIsRequestedDevfunc(pBus->apDevices[iDev]))
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;
2082
if (pBus->apDevices[iDev])
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)
2092
AssertMsgFailed(("Couldn't find free spot!\n"));
2093
return VERR_PDM_TOO_PCI_MANY_DEVICES;
2095
/* Copy device function by function to its new position */
2096
for (int i = 0; i < 8; i++)
2098
if (!pBus->apDevices[iDev + i])
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;
2108
* Fill in device information.
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))
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;
2127
Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
2128
iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
2130
return VINF_SUCCESS;
2133
static void printIndent(PCDBGFINFOHLP pHlp, int iIndent)
2135
for (int i = 0; i < iIndent; i++)
2137
pHlp->pfnPrintf(pHlp, " ");
2141
static void ich9pciBusInfo(PPCIBUS pBus, PCDBGFINFOHLP pHlp, int iIndent, bool fRegisters)
2143
for (uint32_t iDev = 0; iDev < RT_ELEMENTS(pBus->apDevices); iDev++)
2145
PPCIDEVICE pPciDev = pBus->apDevices[iDev];
2146
if (pPciDev != NULL)
2148
printIndent(pHlp, iIndent);
2149
pHlp->pfnPrintf(pHlp, "%02x:%02x:%02x %s: %04x-%04x%s%s",
2150
pBus->iBus, (iDev >> 3) & 0xff, iDev & 0x7,
2152
PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev),
2153
PCIIsMsiCapable(pPciDev) ? " MSI" : "",
2154
PCIIsMsixCapable(pPciDev) ? " MSI-X" : ""
2156
if (PCIDevGetInterruptPin(pPciDev) != 0)
2157
pHlp->pfnPrintf(pHlp, " IRQ%d", PCIDevGetInterruptLine(pPciDev));
2159
pHlp->pfnPrintf(pHlp, "\n");
2161
int iCmd = PCIDevGetCommand(pPciDev);
2162
if ((iCmd & (VBOX_PCI_COMMAND_IO | VBOX_PCI_COMMAND_MEMORY)) != 0)
2164
for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
2166
PCIIORegion* pRegion = &pPciDev->Int.s.aIORegions[iRegion];
2167
int32_t iRegionSize = pRegion->size;
2169
if (iRegionSize == 0)
2172
uint32_t u32Addr = ich9pciConfigReadDev(pPciDev, ich9pciGetRegionReg(iRegion), 4);
2173
const char * szDesc;
2175
if (pRegion->type & PCI_ADDRESS_SPACE_IO)
2186
printIndent(pHlp, iIndent + 2);
2187
pHlp->pfnPrintf(pHlp, " %s region #%d: %x..%x\n",
2188
szDesc, iRegion, u32Addr, u32Addr+iRegionSize);
2194
printIndent(pHlp, iIndent + 2);
2195
pHlp->pfnPrintf(pHlp, " PCI registers:\n");
2196
for (int iReg = 0; iReg < 0x100; )
2198
int iPerLine = 0x10;
2199
Assert (0x100 % iPerLine == 0);
2200
printIndent(pHlp, iIndent + 3);
2202
while (iPerLine-- > 0)
2204
pHlp->pfnPrintf(pHlp, "%02x ", pPciDev->config[iReg++]);
2206
pHlp->pfnPrintf(pHlp, "\n");
2212
if (pBus->cBridges > 0)
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++)
2218
PPCIBUS pBusSub = PDMINS_2_DATA(pBus->papBridgesR3[iBridge]->pDevIns, PPCIBUS);
2219
ich9pciBusInfo(pBusSub, pHlp, iIndent + 1, fRegisters);
2225
* Info handler, device version.
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.
2231
static DECLCALLBACK(void) ich9pciInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2233
PPCIBUS pBus = DEVINS_2_PCIBUS(pDevIns);
2235
if (pszArgs == NULL || !strcmp(pszArgs, "basic"))
2237
ich9pciBusInfo(pBus, pHlp, 0, false);
2239
else if (!strcmp(pszArgs, "verbose"))
2241
ich9pciBusInfo(pBus, pHlp, 0, true);
2245
pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'verbose'.\n");
2250
static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns,
2255
Assert(iInstance == 0);
2258
* Validate and read configuration.
2260
if (!CFGMR3AreValuesValid(pCfg,
2267
return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2269
/* query whether we got an IOAPIC */
2271
rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fUseIoApic, false);
2273
return PDMDEV_SET_ERROR(pDevIns, rc,
2274
N_("Configuration error: Failed to query boolean value \"IOAPIC\""));
2276
/* check if RC code is enabled. */
2278
rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
2280
return PDMDEV_SET_ERROR(pDevIns, rc,
2281
N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
2283
/* check if R0 code is enabled. */
2285
rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
2287
return PDMDEV_SET_ERROR(pDevIns, rc,
2288
N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
2290
Log(("PCI: fUseIoApic=%RTbool fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fUseIoApic, fGCEnabled, fR0Enabled));
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 */
2301
return PDMDEV_SET_ERROR(pDevIns, rc,
2302
N_("Must use IO-APIC with ICH9 chipset"));
2303
rc = CFGMR3QueryU64Def(pCfg, "McfgBase", &pGlobals->u64PciConfigMMioAddress, 0);
2305
return PDMDEV_SET_ERROR(pDevIns, rc,
2306
N_("Configuration error: Failed to read \"McfgBase\""));
2307
rc = CFGMR3QueryU64Def(pCfg, "McfgLength", &pGlobals->u64PciConfigMMioLength, 0);
2309
return PDMDEV_SET_ERROR(pDevIns, rc,
2310
N_("Configuration error: Failed to read \"McfgLength\""));
2312
pGlobals->pDevInsR3 = pDevIns;
2313
pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
2314
pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
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));
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);
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);
2345
pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
2346
pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
2349
* Fill in PCI configs and add them to the bus.
2353
* We emulate 82801IB ICH9 IO chip used in Q35,
2354
* see http://ark.intel.com/Product.aspx?id=31892
2356
* Stepping S-Spec Top Marking
2358
* A2 SLA9M NH82801IB
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);
2374
PCIDevSetWord(&pBus->aPciDev, 0x50, VBOX_PCI_CAP_ID_SSVID);
2375
PCIDevSetDWord(&pBus->aPciDev, 0x54, 0x00000000); /* Subsystem vendor ids */
2377
pBus->aPciDev.pDevIns = pDevIns;
2378
/* We register Host<->PCI controller on the bus */
2379
ich9pciRegisterInternal(pBus, -1, &pBus->aPciDev, "i82801");
2382
* Register I/O ports and save state.
2384
rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 1, NULL, ich9pciIOPortAddressWrite, ich9pciIOPortAddressRead, NULL, NULL, "ICH9 (PCI)");
2387
rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cfc, 4, NULL, ich9pciIOPortDataWrite, ich9pciIOPortDataRead, NULL, NULL, "ICH9 (PCI)");
2392
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cf8, 1, NIL_RTGCPTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
2395
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x0cfc, 4, NIL_RTGCPTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
2401
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cf8, 1, NIL_RTR0PTR, "ich9pciIOPortAddressWrite", "ich9pciIOPortAddressRead", NULL, NULL, "ICH9 (PCI)");
2404
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x0cfc, 4, NIL_RTR0PTR, "ich9pciIOPortDataWrite", "ich9pciIOPortDataRead", NULL, NULL, "ICH9 (PCI)");
2409
if (pGlobals->u64PciConfigMMioAddress != 0)
2411
rc = PDMDevHlpMMIORegister(pDevIns,
2412
pGlobals->u64PciConfigMMioAddress,
2413
pGlobals->u64PciConfigMMioLength,
2415
ich9pciMcfgMMIOWrite,
2416
ich9pciMcfgMMIORead,
2421
AssertMsgRC(rc, ("Cannot register MCFG MMIO: %Rrc\n", rc));
2428
rc = PDMDevHlpMMIORegisterRC(pDevIns,
2429
pGlobals->u64PciConfigMMioAddress,
2430
pGlobals->u64PciConfigMMioLength,
2432
"ich9pciMcfgMMIOWrite",
2433
"ich9pciMcfgMMIORead",
2437
AssertMsgRC(rc, ("Cannot register MCFG MMIO (GC): %Rrc\n", rc));
2446
rc = PDMDevHlpMMIORegisterR0(pDevIns,
2447
pGlobals->u64PciConfigMMioAddress,
2448
pGlobals->u64PciConfigMMioLength,
2450
"ich9pciMcfgMMIOWrite",
2451
"ich9pciMcfgMMIORead",
2455
AssertMsgRC(rc, ("Cannot register MCFG MMIO (R0): %Rrc\n", rc));
2461
rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
2462
sizeof(*pBus) + 16*128, "pgm",
2464
NULL, ich9pciR3SaveExec, NULL,
2465
NULL, ich9pciR3LoadExec, NULL);
2470
/** @todo: other chipset devices shall be registered too */
2471
/** @todo: what to with bridges? */
2473
PDMDevHlpDBGFInfoRegister(pDevIns, "pci", "Display PCI bus status. (no arguments)", ich9pciInfo);
2475
return VINF_SUCCESS;
2478
static void ich9pciResetDevice(PPCIDEVICE pDev)
2480
PPCIBUS pBus = pDev->Int.s.CTX_SUFF(pBus);
2484
for (int iRegion = 0; iRegion < PCI_NUM_REGIONS; iRegion++)
2486
PCIIORegion* pRegion = &pDev->Int.s.aIORegions[iRegion];
2487
if (pRegion->size == 0)
2490
ich9pciUnmapRegion(pDev, iRegion);
2493
PCIDevSetCommand(pDev,
2494
PCIDevGetCommand(pDev)
2496
~(VBOX_PCI_COMMAND_IO |
2497
VBOX_PCI_COMMAND_MEMORY |
2498
VBOX_PCI_COMMAND_MASTER));
2500
/* Bridge device reset handlers processed later */
2501
if (!PCIIsPci2PciBridge(pDev))
2503
PCIDevSetByte(pDev, VBOX_PCI_CACHE_LINE_SIZE, 0x0);
2504
PCIDevSetInterruptLine(pDev, 0x0);
2510
* @copydoc FNPDMDEVRESET
2512
static DECLCALLBACK(void) ich9pciReset(PPDMDEVINS pDevIns)
2514
PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
2515
PPCIBUS pBus = &pGlobals->aPciBus;
2517
/* PCI-specific reset for each device. */
2518
for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
2520
if (pBus->apDevices[i])
2521
ich9pciResetDevice(pBus->apDevices[i]);
2524
for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
2526
if (pBus->papBridgesR3[iBridge])
2527
ich9pcibridgeReset(pBus->papBridgesR3[iBridge]->pDevIns);
2530
ich9pciFakePCIBIOS(pDevIns);
2533
static void ich9pciRelocateDevice(PPCIDEVICE pDev, RTGCINTPTR offDelta)
2537
pDev->Int.s.pBusRC += offDelta;
2538
if (pDev->Int.s.pMsixPageRC)
2539
pDev->Int.s.pMsixPageRC += offDelta;
2544
* @copydoc FNPDMDEVRELOCATE
2546
static DECLCALLBACK(void) ich9pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
2548
PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
2549
PPCIBUS pBus = &pGlobals->aPciBus;
2550
pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
2552
pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
2553
pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
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);
2562
* @interface_method_impl{PDMDEVREG,pfnConstruct}
2564
static DECLCALLBACK(int) ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
2571
* Validate and read configuration.
2573
if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
2574
return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
2576
/* check if RC code is enabled. */
2578
rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
2580
return PDMDEV_SET_ERROR(pDevIns, rc,
2581
N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
2583
/* check if R0 code is enabled. */
2585
rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
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));
2592
* Init data and register the PCI bus.
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));
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);
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);
2621
pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
2622
pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
2625
* Fill in PCI configs and add them to the bus.
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. */
2639
* This device does not generate interrupts. Interrupt delivery from
2640
* devices attached to the bus is unaffected.
2642
PCIDevSetInterruptPin (&pBus->aPciDev, 0x00);
2644
pBus->aPciDev.pDevIns = pDevIns;
2646
/* Bridge-specific data */
2647
PCISetPci2PciBridge(&pBus->aPciDev);
2648
pBus->aPciDev.Int.s.pfnBridgeConfigRead = ich9pcibridgeConfigRead;
2649
pBus->aPciDev.Int.s.pfnBridgeConfigWrite = ich9pcibridgeConfigWrite;
2652
* Register this PCI bridge. The called function will take care on which bus we will get registered.
2654
rc = PDMDevHlpPCIRegister (pDevIns, &pBus->aPciDev);
2659
* The iBus property doesn't really represent the bus number
2660
* because the guest and the BIOS can choose different bus numbers
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.
2666
pBus->iBus = iInstance + 1;
2669
* Register SSM handlers. We use the same saved state version as for the host bridge
2670
* to make changes easier.
2672
rc = PDMDevHlpSSMRegisterEx(pDevIns, VBOX_ICH9PCI_SAVED_STATE_VERSION_CURRENT,
2673
sizeof(*pBus) + 16*128,
2676
NULL, ich9pcibridgeR3SaveExec, NULL,
2677
NULL, ich9pcibridgeR3LoadExec, NULL);
2682
return VINF_SUCCESS;
2686
* @copydoc FNPDMDEVRESET
2688
static void ich9pcibridgeReset(PPDMDEVINS pDevIns)
2690
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
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);
2697
/* PCI-specific reset for each device. */
2698
for (uint32_t i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
2700
if (pBus->apDevices[i])
2701
ich9pciResetDevice(pBus->apDevices[i]);
2707
* @copydoc FNPDMDEVRELOCATE
2709
static DECLCALLBACK(void) ich9pcibridgeRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
2711
PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS);
2712
pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
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);
2720
* The PCI bus device registration structure.
2722
const PDMDEVREG g_DevicePciIch9 =
2732
/* pszDescription */
2735
PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
2737
PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
2762
/* pfnQueryInterface */
2764
/* pfnInitComplete */
2775
* The device registration structure
2776
* for the PCI-to-PCI bridge.
2778
const PDMDEVREG g_DevicePciIch9Bridge =
2788
/* pszDescription */
2789
"ICH9 PCI to PCI bridge",
2791
PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
2793
PDM_DEVREG_CLASS_BUS_PCI,
2799
ich9pcibridgeConstruct,
2803
ich9pcibridgeRelocate,
2809
NULL, /* Must be NULL, to make sure only bus driver handles reset */
2818
/* pfnQueryInterface */
2820
/* pfnInitComplete */
2830
#endif /* IN_RING3 */
2831
#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */