VirtualBox

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

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

scm whitespace cleanup

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