VirtualBox

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

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

PCI: device assignment logic

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/* $Id: DevPciIch9.cpp 32216 2010-09-02 15:32:04Z 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/pdmdev.h>
26#include <iprt/asm.h>
27#include <iprt/assert.h>
28#include <iprt/string.h>
29
30#include "../Builtins.h"
31
32/**
33 * PCI Bus instance.
34 */
35typedef struct PCIBus
36{
37 /** Bus number. */
38 int32_t iBus;
39 /** Number of bridges attached to the bus. */
40 uint32_t cBridges;
41
42 /** Array of PCI devices. We assume 32 slots, each with 8 functions. */
43 R3PTRTYPE(PPCIDEVICE) devices[256];
44 /** Array of bridges attached to the bus. */
45 R3PTRTYPE(PPCIDEVICE *) papBridgesR3;
46
47 /** R3 pointer to the device instance. */
48 PPDMDEVINSR3 pDevInsR3;
49 /** Pointer to the PCI R3 helpers. */
50 PCPDMPCIHLPR3 pPciHlpR3;
51
52 /** R0 pointer to the device instance. */
53 PPDMDEVINSR0 pDevInsR0;
54 /** Pointer to the PCI R0 helpers. */
55 PCPDMPCIHLPR0 pPciHlpR0;
56
57 /** RC pointer to the device instance. */
58 PPDMDEVINSRC pDevInsRC;
59 /** Pointer to the PCI RC helpers. */
60 PCPDMPCIHLPRC pPciHlpRC;
61
62 /** The PCI device for the PCI bridge. */
63 PCIDEVICE PciDev;
64
65} PCIBUS, *PPCIBUS;
66
67
68/** @def PCI_IRQ_PINS
69 * Number of pins for interrupts (PIRQ#0...PIRQ#3)
70 */
71#define PCI_IRQ_PINS 4
72
73/** @def PCI_APIC_IRQ_PINS
74 * Number of pins for interrupts if the APIC is used.
75 */
76#define PCI_APIC_IRQ_PINS 8
77
78/**
79 * PCI Globals - This is the host-to-pci bridge and the root bus.
80 */
81typedef struct
82{
83 /** R3 pointer to the device instance. */
84 PPDMDEVINSR3 pDevInsR3;
85 /** R0 pointer to the device instance. */
86 PPDMDEVINSR0 pDevInsR0;
87 /** RC pointer to the device instance. */
88 PPDMDEVINSRC pDevInsRC;
89
90#if HC_ARCH_BITS == 64
91 uint32_t Alignment0;
92#endif
93
94 /** PIC irq levels */
95 volatile uint32_t uaPicPciIrqLevels[PCI_IRQ_PINS];
96 /** I/O APIC irq levels */
97 volatile uint32_t uaPciApicIrqLevels[PCI_APIC_IRQ_PINS];
98
99 /** ACPI IRQ level */
100 uint32_t uAcpiIrqLevel;
101 /** .. and number */
102 uint32_t uAcpiIrq;
103
104 /** Config register. */
105 uint32_t uConfigReg;
106
107 /** I/O APIC usage flag */
108 bool fUseIoApic;
109
110
111 /** PCI bus which is attached to the host-to-PCI bridge. */
112 PCIBUS aPciBus;
113
114} PCIGLOBALS, *PPCIGLOBALS;
115
116
117/*******************************************************************************
118 * Defined Constants And Macros *
119 *******************************************************************************/
120
121/** @def VBOX_ICH9PCI_SAVED_STATE_VERSION
122 * Saved state version of the ICH9 PCI bus device.
123 */
124#define VBOX_ICH9PCI_SAVED_STATE_VERSION 1
125
126/** Converts a bus instance pointer to a device instance pointer. */
127#define PCIBUS_2_DEVINS(pPciBus) ((pPciBus)->CTX_SUFF(pDevIns))
128/** Converts a device instance pointer to a PCIGLOBALS pointer. */
129#define DEVINS_2_PCIGLOBALS(pDevIns) ((PPCIGLOBALS)(PDMINS_2_DATA(pDevIns, PPCIGLOBALS)))
130/** Converts a device instance pointer to a PCIBUS pointer. */
131#define DEVINS_2_PCIBUS(pDevIns) ((PPCIBUS)(&PDMINS_2_DATA(pDevIns, PPCIGLOBALS)->aPciBus))
132
133#ifndef VBOX_DEVICE_STRUCT_TESTCASE
134
135RT_C_DECLS_BEGIN
136
137PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
138PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
139PDMBOTHCBDECL(int) ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
140PDMBOTHCBDECL(int) ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
141PDMBOTHCBDECL(int) ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
142PDMBOTHCBDECL(int) ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
143
144#ifdef IN_RING3
145DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus);
146#endif
147
148RT_C_DECLS_END
149
150
151PDMBOTHCBDECL(void) ich9pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
152{
153 return;
154}
155
156PDMBOTHCBDECL(void) ich9pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
157{
158 return;
159}
160
161PDMBOTHCBDECL(int) ich9pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
162{
163 return 0;
164}
165
166PDMBOTHCBDECL(int) ich9pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
167{
168 return 0;
169}
170
171PDMBOTHCBDECL(int) ich9pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
172{
173 return 0;
174}
175
176PDMBOTHCBDECL(int) ich9pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
177{
178 return 0;
179}
180
181#ifdef IN_RING3
182DECLINLINE(PPCIDEVICE) ich9pciFindBridge(PPCIBUS pBus, uint8_t iBus);
183#endif
184
185#ifdef IN_RING3
186
187static DECLCALLBACK(int) ich9pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
188{
189 return 0;
190}
191
192static DECLCALLBACK(int) ich9pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
193{
194 return 0;
195}
196
197static DECLCALLBACK(int) ich9pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
198{
199 return 0;
200}
201
202static DECLCALLBACK(void) ich9pciSetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
203 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
204{
205}
206
207/**
208 * Saves a state of the PCI device.
209 *
210 * @returns VBox status code.
211 * @param pDevIns Device instance of the PCI Bus.
212 * @param pPciDev Pointer to PCI device.
213 * @param pSSM The handle to save the state to.
214 */
215static DECLCALLBACK(int) pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
216{
217 return SSMR3PutMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
218}
219
220static int pciR3CommonSaveExec(PPCIBUS pBus, PSSMHANDLE pSSM)
221{
222 /*
223 * Iterate thru all the devices.
224 */
225 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++)
226 {
227 PPCIDEVICE pDev = pBus->devices[i];
228 if (pDev)
229 {
230 SSMR3PutU32(pSSM, i);
231 SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config));
232
233 int rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
234 if (RT_FAILURE(rc))
235 return rc;
236 }
237 }
238 return SSMR3PutU32(pSSM, UINT32_MAX); /* terminator */
239}
240
241static DECLCALLBACK(int) pciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
242{
243 PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
244 return pciR3CommonSaveExec(pThis, pSSM);
245}
246
247
248static DECLCALLBACK(int) pcibridgeR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
249{
250 PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
251 return pciR3CommonSaveExec(pThis, pSSM);
252}
253
254static DECLCALLBACK(int) pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
255{
256 return 0;
257}
258
259/**
260 * Loads a saved PCI device state.
261 *
262 * @returns VBox status code.
263 * @param pDevIns Device instance of the PCI Bus.
264 * @param pPciDev Pointer to PCI device.
265 * @param pSSM The handle to the saved state.
266 */
267static DECLCALLBACK(int) pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSM)
268{
269 return SSMR3GetMem(pSSM, &pPciDev->config[0], sizeof(pPciDev->config));
270}
271
272static DECLCALLBACK(int) pciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
273{
274 PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
275 if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
276 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
277 return pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
278}
279
280static DECLCALLBACK(int) pcibridgeR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
281{
282 PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);
283 if (uVersion > VBOX_ICH9PCI_SAVED_STATE_VERSION)
284 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
285 return pciR3CommonLoadExec(pThis, pSSM, uVersion, uPass);
286}
287
288static DECLCALLBACK(int) ich9pciFakePCIBIOS(PPDMDEVINS pDevIns)
289{
290 return 0;
291}
292
293static DECLCALLBACK(uint32_t) ich9pciConfigRead(PCIDevice *aDev, uint32_t u32Address, unsigned len)
294{
295 if (u32Address + len >= 256)
296 {
297 Assert(false);
298 return 0;
299 }
300
301 switch (len)
302 {
303 case 1:
304 return aDev->config[u32Address];
305 case 2:
306 return RT_LE2H_U16(*(uint16_t *)(aDev->config + u32Address));
307 default:
308 case 4:
309 return RT_LE2H_U32(*(uint32_t *)(aDev->config + u32Address));
310 }
311}
312
313
314static DECLCALLBACK(void) ich9pciConfigWrite(PCIDevice *aDev, uint32_t u32Address, uint32_t val, unsigned len)
315{
316 // @todo: write me
317}
318
319/* Slot/functions assignment per table at p. 12 of ICH9 family spec update */
320static const struct {
321 const char* pszName;
322 int32_t iSlot;
323 int32_t iFunction;
324} PciSlotAssignments[] = {
325 {
326 "piix3ide", 1, 1 // do we really need it?
327 },
328 {
329 "lan", 25, 0
330 },
331 {
332 "hda", 27, 0 /* High Definition Audio */
333 },
334 {
335 "i82801", 30, 0 /* Host Controller */
336 },
337 {
338 "lpc", 31, 0 /* Low Pin Count bus */
339 },
340 {
341 "ahci", 31, 2 /* SATA controller */
342 },
343 {
344 "smbus", 31, 3 /* System Management Bus */
345 },
346 {
347 "thermal", 31, 6 /* Thermal controller */
348 },
349};
350static int assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName)
351{
352 /* Hardcoded slots/functions, per chipset spec */
353 for (size_t i = 0; i < RT_ELEMENTS(PciSlotAssignments); i++)
354 {
355 if (!strcmp(pszName, PciSlotAssignments[i].pszName))
356 {
357 pPciDev->Int.s.fRequestedDevFn = true;
358 return (PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
359 }
360 }
361
362 /* Otherwise when assigning a slot, we need to make sure all its functions are available */
363 for (int iPos = 0; iPos < (int)RT_ELEMENTS(pBus->devices); iPos += 8)
364 if ( !pBus->devices[iPos]
365 && !pBus->devices[iPos + 1]
366 && !pBus->devices[iPos + 2]
367 && !pBus->devices[iPos + 3]
368 && !pBus->devices[iPos + 4]
369 && !pBus->devices[iPos + 5]
370 && !pBus->devices[iPos + 6]
371 && !pBus->devices[iPos + 7])
372 {
373 pPciDev->Int.s.fRequestedDevFn = false;
374 return iPos;
375 }
376
377 return -1;
378}
379
380static bool hasHardAssignedDevsInSlot(PPCIBUS pBus, int iSlot)
381{
382 PCIDevice** aSlot = &pBus->devices[iSlot << 3];
383
384 return (aSlot[0] && aSlot[0]->Int.s.fRequestedDevFn)
385 || (aSlot[1] && aSlot[1]->Int.s.fRequestedDevFn)
386 || (aSlot[2] && aSlot[2]->Int.s.fRequestedDevFn)
387 || (aSlot[3] && aSlot[3]->Int.s.fRequestedDevFn)
388 || (aSlot[4] && aSlot[4]->Int.s.fRequestedDevFn)
389 || (aSlot[5] && aSlot[5]->Int.s.fRequestedDevFn)
390 || (aSlot[6] && aSlot[6]->Int.s.fRequestedDevFn)
391 || (aSlot[7] && aSlot[7]->Int.s.fRequestedDevFn)
392 ;
393}
394
395static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
396{
397 /*
398 * Find device position
399 */
400 if (iDev < 0)
401 {
402 iDev = assignPosition(pBus, pPciDev, pszName);
403 if (iDev < 0)
404 {
405 AssertMsgFailed(("Couldn't find free spot!\n"));
406 return VERR_PDM_TOO_PCI_MANY_DEVICES;
407 }
408 }
409
410 /*
411 * Check if we can really take this slot, possibly by relocating
412 * its current habitant, if it wasn't hard assigned too.
413 */
414 if (pPciDev->Int.s.fRequestedDevFn &&
415 pBus->devices[iDev] &&
416 pBus->devices[iDev]->Int.s.fRequestedDevFn)
417 {
418 /*
419 * Smth like hasHardAssignedDevsInSlot(pBus, iDev >> 3) shall be use to make
420 * it compatible with DevPCI.cpp version, but this way we cannot assign
421 * in accordance with the chipset spec.
422 */
423 AssertReleaseMsgFailed(("Configuration error:'%s' and '%s' are both configured as device %d\n",
424 pszName, pBus->devices[iDev]->name, iDev));
425 return VERR_INTERNAL_ERROR;
426 }
427
428 if (pBus->devices[iDev])
429 {
430 /* if we got here, we shall (and usually can) relocate the device */
431 int iRelDev = assignPosition(pBus, pBus->devices[iDev], pBus->devices[iDev]->name);
432 if (iRelDev < 0 || iRelDev == iDev)
433 {
434 AssertMsgFailed(("Couldn't find free spot!\n"));
435 return VERR_PDM_TOO_PCI_MANY_DEVICES;
436 }
437 /* Copy device function by function to its new position */
438 for (int i = 0; i < 8; i++)
439 {
440 if (!pBus->devices[iDev + i])
441 continue;
442 Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->devices[iDev + i]->name, iDev + i, iRelDev + i));
443 pBus->devices[iRelDev + i] = pBus->devices[iDev + i];
444 pBus->devices[iRelDev + i]->devfn = i;
445 pBus->devices[iDev + i] = NULL;
446 }
447 }
448
449 /*
450 * Fill in device information.
451 */
452 pPciDev->devfn = iDev;
453 pPciDev->name = pszName;
454 pPciDev->Int.s.pBusR3 = pBus;
455 pPciDev->Int.s.pBusR0 = MMHyperR3ToR0(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
456 pPciDev->Int.s.pBusRC = MMHyperR3ToRC(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
457 pPciDev->Int.s.pfnConfigRead = ich9pciConfigRead;
458 pPciDev->Int.s.pfnConfigWrite = ich9pciConfigWrite;
459 pBus->devices[iDev] = pPciDev;
460 if (pPciDev->Int.s.fPciToPciBridge)
461 {
462 AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->devices), ("Number of bridges exceeds the number of possible devices on the bus\n"));
463 AssertMsg(pPciDev->Int.s.pfnBridgeConfigRead && pPciDev->Int.s.pfnBridgeConfigWrite,
464 ("device is a bridge but does not implement read/write functions\n"));
465 pBus->papBridgesR3[pBus->cBridges] = pPciDev;
466 pBus->cBridges++;
467 }
468
469 Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
470 iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
471
472 return VINF_SUCCESS;
473}
474
475static DECLCALLBACK(int) ich9pciConstruct(PPDMDEVINS pDevIns,
476 int iInstance,
477 PCFGMNODE pCfg)
478{
479 int rc;
480 Assert(iInstance == 0);
481
482 /*
483 * Validate and read configuration.
484 */
485 if (!CFGMR3AreValuesValid(pCfg, "IOAPIC\0" "GCEnabled\0" "R0Enabled\0"))
486 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
487
488 /* query whether we got an IOAPIC */
489 bool fUseIoApic;
490 rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fUseIoApic, false);
491 if (RT_FAILURE(rc))
492 return PDMDEV_SET_ERROR(pDevIns, rc,
493 N_("Configuration error: Failed to query boolean value \"IOAPIC\""));
494
495 /* check if RC code is enabled. */
496 bool fGCEnabled;
497 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
498 if (RT_FAILURE(rc))
499 return PDMDEV_SET_ERROR(pDevIns, rc,
500 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
501
502 /* check if R0 code is enabled. */
503 bool fR0Enabled;
504 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
505 if (RT_FAILURE(rc))
506 return PDMDEV_SET_ERROR(pDevIns, rc,
507 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
508 Log(("PCI: fUseIoApic=%RTbool fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fUseIoApic, fGCEnabled, fR0Enabled));
509
510 /*
511 * Init data.
512 */
513 PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
514 PPCIBUS pBus = &pGlobals->aPciBus;
515 /* Zero out everything */
516 memset(pGlobals, 0, sizeof(*pGlobals));
517 /* And fill values */
518 pGlobals->fUseIoApic = fUseIoApic;
519 pGlobals->pDevInsR3 = pDevIns;
520 pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
521 pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
522
523 pGlobals->aPciBus.pDevInsR3 = pDevIns;
524 pGlobals->aPciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
525 pGlobals->aPciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
526 pGlobals->aPciBus.papBridgesR3 = (PPCIDEVICE *)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(PPCIDEVICE) * RT_ELEMENTS(pGlobals->aPciBus.devices));
527
528 /*
529 * Register bus
530 */
531 PDMPCIBUSREG PciBusReg;
532 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
533 PciBusReg.pfnRegisterR3 = ich9pciRegister;
534 PciBusReg.pfnIORegionRegisterR3 = ich9pciIORegionRegister;
535 PciBusReg.pfnSetConfigCallbacksR3 = ich9pciSetConfigCallbacks;
536 PciBusReg.pfnSetIrqR3 = ich9pciSetIrq;
537 PciBusReg.pfnSaveExecR3 = pciGenericSaveExec;
538 PciBusReg.pfnLoadExecR3 = pciGenericLoadExec;
539 PciBusReg.pfnFakePCIBIOSR3 = ich9pciFakePCIBIOS;
540 PciBusReg.pszSetIrqRC = fGCEnabled ? "ich9pciSetIrq" : NULL;
541 PciBusReg.pszSetIrqR0 = fR0Enabled ? "ich9pciSetIrq" : NULL;
542 rc = PDMDevHlpPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
543 if (RT_FAILURE(rc))
544 return PDMDEV_SET_ERROR(pDevIns, rc,
545 N_("Failed to register ourselves as a PCI Bus"));
546 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION)
547 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
548 N_("PCI helper version mismatch; got %#x expected %#x"),
549 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION);
550
551 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns);
552 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
553
554 /*
555 * Fill in PCI configs and add them to the bus.
556 */
557
558 /**
559 * We emulate 82801IB ICH9 IO chip used in Q35,
560 * see http://ark.intel.com/Product.aspx?id=31892
561 *
562 * Stepping S-Spec Top Marking
563 *
564 * A2 SLA9M NH82801IB
565 */
566 PCIDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */
567 PCIDevSetDeviceId( &pBus->PciDev, 0x244e); /* Desktop */
568 PCIDevSetRevisionId(&pBus->PciDev, 0x92); /* rev. A2 */
569 PCIDevSetClassSub( &pBus->PciDev, 0x00); /* Host/PCI bridge */
570 PCIDevSetClassBase( &pBus->PciDev, 0x06); /* bridge */
571 PCIDevSetHeaderType(&pBus->PciDev, 0x00);
572
573 pBus->PciDev.pDevIns = pDevIns;
574 pBus->PciDev.Int.s.fRequestedDevFn= true;
575 /* We register Host<->PCI controller on the bus */
576 ich9pciRegisterInternal(pBus, 0, &pBus->PciDev, "i82801");
577
578 /** @todo: ther chipset devices shall be registered too */
579 /** @todo: bridges? */
580
581 return VINF_SUCCESS;
582}
583
584/**
585 * @copydoc FNPDMDEVRELOCATE
586 */
587static DECLCALLBACK(void) ich9pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
588{
589}
590
591/**
592 * @interface_method_impl{PDMDEVREG,pfnConstruct}
593 */
594static DECLCALLBACK(int) ich9pcibridgeConstruct(PPDMDEVINS pDevIns,
595 int iInstance,
596 PCFGMNODE pCfg)
597{
598 int rc;
599
600 /*
601 * Validate and read configuration.
602 */
603 if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
604 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
605
606 /* check if RC code is enabled. */
607 bool fGCEnabled;
608 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
609 if (RT_FAILURE(rc))
610 return PDMDEV_SET_ERROR(pDevIns, rc,
611 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
612
613 /* check if R0 code is enabled. */
614 bool fR0Enabled;
615 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
616 if (RT_FAILURE(rc))
617 return PDMDEV_SET_ERROR(pDevIns, rc,
618 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
619 Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled));
620
621 return VINF_SUCCESS;
622}
623
624/**
625 * @copydoc FNPDMDEVRESET
626 */
627static DECLCALLBACK(void) ich9pcibridgeReset(PPDMDEVINS pDevIns)
628{
629}
630
631
632/**
633 * @copydoc FNPDMDEVRELOCATE
634 */
635static DECLCALLBACK(void) ich9pcibridgeRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
636{
637}
638
639/**
640 * The PCI bus device registration structure.
641 */
642const PDMDEVREG g_DevicePciIch9 =
643{
644 /* u32Version */
645 PDM_DEVREG_VERSION,
646 /* szName */
647 "ich9pci",
648 /* szRCMod */
649 "VBoxDDGC.gc",
650 /* szR0Mod */
651 "VBoxDDR0.r0",
652 /* pszDescription */
653 "ICH9 PCI bridge",
654 /* fFlags */
655 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
656 /* fClass */
657 PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
658 /* cMaxInstances */
659 1,
660 /* cbInstance */
661 sizeof(PCIGLOBALS),
662 /* pfnConstruct */
663 ich9pciConstruct,
664 /* pfnDestruct */
665 NULL,
666 /* pfnRelocate */
667 ich9pciRelocate,
668 /* pfnIOCtl */
669 NULL,
670 /* pfnPowerOn */
671 NULL,
672 /* pfnReset */
673 NULL,
674 /* pfnSuspend */
675 NULL,
676 /* pfnResume */
677 NULL,
678 /* pfnAttach */
679 NULL,
680 /* pfnDetach */
681 NULL,
682 /* pfnQueryInterface */
683 NULL,
684 /* pfnInitComplete */
685 NULL,
686 /* pfnPowerOff */
687 NULL,
688 /* pfnSoftReset */
689 NULL,
690 /* u32VersionEnd */
691 PDM_DEVREG_VERSION
692};
693
694/**
695 * The device registration structure
696 * for the PCI-to-PCI bridge.
697 */
698const PDMDEVREG g_DevicePciIch9Bridge =
699{
700 /* u32Version */
701 PDM_DEVREG_VERSION,
702 /* szName */
703 "ich9pcibridge",
704 /* szRCMod */
705 "VBoxDDGC.gc",
706 /* szR0Mod */
707 "VBoxDDR0.r0",
708 /* pszDescription */
709 "ICH9 PCI to PCI bridge",
710 /* fFlags */
711 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
712 /* fClass */
713 PDM_DEVREG_CLASS_BUS_PCI,
714 /* cMaxInstances */
715 ~0,
716 /* cbInstance */
717 sizeof(PCIBUS),
718 /* pfnConstruct */
719 ich9pcibridgeConstruct,
720 /* pfnDestruct */
721 NULL,
722 /* pfnRelocate */
723 ich9pcibridgeRelocate,
724 /* pfnIOCtl */
725 NULL,
726 /* pfnPowerOn */
727 NULL,
728 /* pfnReset */
729 ich9pcibridgeReset,
730 /* pfnSuspend */
731 NULL,
732 /* pfnResume */
733 NULL,
734 /* pfnAttach */
735 NULL,
736 /* pfnDetach */
737 NULL,
738 /* pfnQueryInterface */
739 NULL,
740 /* pfnInitComplete */
741 NULL,
742 /* pfnPowerOff */
743 NULL,
744 /* pfnSoftReset */
745 NULL,
746 /* u32VersionEnd */
747 PDM_DEVREG_VERSION
748};
749
750#endif /* IN_RING3 */
751#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