VirtualBox

source: vbox/trunk/src/VBox/Devices/Bus/DevPciIch9.cpp@ 33027

Last change on this file since 33027 was 32960, checked in by vboxsync, 14 years ago

PCI: bad typo in PCI address computation, now Windows boots fine with MCFG

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

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