VirtualBox

source: vbox/trunk/include/VBox/vmm/pdmpcidev.h@ 82073

Last change on this file since 82073 was 82073, checked in by vboxsync, 5 years ago

DevPCI: Added a special return code to FNPCIIOREGIONMAP for telling the bus that the callback did the mapping and it should not use the registered handle to do so again. Needed for VGA (alternative was to reorder the callout order). bugref:9218

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.9 KB
Line 
1/** @file
2 * PCI - The PCI Controller And Devices. (DEV)
3 */
4
5/*
6 * Copyright (C) 2006-2019 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef VBOX_INCLUDED_vmm_pdmpcidev_h
27#define VBOX_INCLUDED_vmm_pdmpcidev_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <VBox/pci.h>
33#include <iprt/assert.h>
34
35
36/** @defgroup grp_pdm_pcidev PDM PCI Device
37 * @ingroup grp_pdm_device
38 * @{
39 */
40
41/**
42 * Callback function for intercept reading from the PCI configuration space.
43 *
44 * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status (maybe others later).
45 * @retval VINF_PDM_PCI_DO_DEFAULT to do default read (same as calling
46 * PDMDevHlpPCIConfigRead()).
47 *
48 * @param pDevIns Pointer to the device instance the PCI device
49 * belongs to.
50 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
51 * @param uAddress The configuration space register address. [0..4096]
52 * @param cb The register size. [1,2,4]
53 * @param pu32Value Where to return the register value.
54 *
55 * @remarks Called with the PDM lock held. The device lock is NOT take because
56 * that is very likely be a lock order violation.
57 */
58typedef DECLCALLBACK(VBOXSTRICTRC) FNPCICONFIGREAD(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
59 uint32_t uAddress, unsigned cb, uint32_t *pu32Value);
60/** Pointer to a FNPCICONFIGREAD() function. */
61typedef FNPCICONFIGREAD *PFNPCICONFIGREAD;
62/** Pointer to a PFNPCICONFIGREAD. */
63typedef PFNPCICONFIGREAD *PPFNPCICONFIGREAD;
64
65/**
66 * Callback function for writing to the PCI configuration space.
67 *
68 * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status (maybe others later).
69 * @retval VINF_PDM_PCI_DO_DEFAULT to do default read (same as calling
70 * PDMDevHlpPCIConfigWrite()).
71 *
72 * @param pDevIns Pointer to the device instance the PCI device
73 * belongs to.
74 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
75 * @param uAddress The configuration space register address. [0..4096]
76 * @param cb The register size. [1,2,4]
77 * @param u32Value The value that's being written. The number of bits actually used from
78 * this value is determined by the cb parameter.
79 *
80 * @remarks Called with the PDM lock held. The device lock is NOT take because
81 * that is very likely be a lock order violation.
82 */
83typedef DECLCALLBACK(VBOXSTRICTRC) FNPCICONFIGWRITE(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
84 uint32_t uAddress, unsigned cb, uint32_t u32Value);
85/** Pointer to a FNPCICONFIGWRITE() function. */
86typedef FNPCICONFIGWRITE *PFNPCICONFIGWRITE;
87/** Pointer to a PFNPCICONFIGWRITE. */
88typedef PFNPCICONFIGWRITE *PPFNPCICONFIGWRITE;
89
90/**
91 * Callback function for mapping an PCI I/O region.
92 *
93 * This is called when a PCI I/O region is mapped, and for new-style devices
94 * also when unmapped (address set to NIL_RTGCPHYS). For new-style devices,
95 * this callback is optional as the PCI bus calls IOM to map and unmap the
96 * regions.
97 *
98 * Old style devices have to call IOM to map the region themselves, while
99 * unmapping is done by the PCI bus like with the new style devices.
100 *
101 * @returns VBox status code.
102 * @retval VINF_PCI_MAPPING_DONE if the caller already did the mapping and the
103 * PCI bus should not use the handle it got to do the registration
104 * again. (Only allowed when @a GCPhysAddress is not NIL_RTGCPHYS.)
105 *
106 * @param pDevIns Pointer to the device instance the PCI device
107 * belongs to.
108 * @param pPciDev Pointer to the PCI device.
109 * @param iRegion The region number.
110 * @param GCPhysAddress Physical address of the region. If @a enmType is
111 * PCI_ADDRESS_SPACE_IO, this is an I/O port, otherwise
112 * it's a physical address.
113 *
114 * NIL_RTGCPHYS indicates that a mapping is about to be
115 * unmapped and that the device deregister access
116 * handlers for it and update its internal state to
117 * reflect this.
118 *
119 * @param cb Size of the region in bytes.
120 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
121 *
122 * @remarks Called with the PDM lock held. The device lock is NOT take because
123 * that is very likely be a lock order violation.
124 */
125typedef DECLCALLBACK(int) FNPCIIOREGIONMAP(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
126 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType);
127/** Pointer to a FNPCIIOREGIONMAP() function. */
128typedef FNPCIIOREGIONMAP *PFNPCIIOREGIONMAP;
129
130
131/**
132 * Sets the size and type for old saved states from within a
133 * PDMPCIDEV::pfnRegionLoadChangeHookR3 callback.
134 *
135 * @returns VBox status code.
136 * @param pPciDev Pointer to the PCI device.
137 * @param iRegion The region number.
138 * @param cbRegion The region size.
139 * @param enmType Combination of the PCI_ADDRESS_SPACE_* values.
140 */
141typedef DECLCALLBACK(int) FNPCIIOREGIONOLDSETTER(PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion, PCIADDRESSSPACE enmType);
142/** Pointer to a FNPCIIOREGIONOLDSETTER() function. */
143typedef FNPCIIOREGIONOLDSETTER *PFNPCIIOREGIONOLDSETTER;
144
145/**
146 * Swaps two PCI I/O regions from within a PDMPCIDEV::pfnRegionLoadChangeHookR3
147 * callback.
148 *
149 * @returns VBox status code.
150 * @param pPciDev Pointer to the PCI device.
151 * @param iRegion The region number.
152 * @param iOtherRegion The number of the region swap with.
153 * @sa @bugref{9359}
154 */
155typedef DECLCALLBACK(int) FNPCIIOREGIONSWAP(PPDMPCIDEV pPciDev, uint32_t iRegion, uint32_t iOtherRegion);
156/** Pointer to a FNPCIIOREGIONSWAP() function. */
157typedef FNPCIIOREGIONSWAP *PFNPCIIOREGIONSWAP;
158
159
160/*
161 * Hack to include the PDMPCIDEVINT structure at the right place
162 * to avoid duplications of FNPCIIOREGIONMAP and such.
163 */
164#ifdef PDMPCIDEV_INCLUDE_PRIVATE
165# include "pdmpcidevint.h"
166#endif
167
168/**
169 * PDM PCI Device structure.
170 *
171 * A PCI device belongs to a PDM device. A PDM device may have zero or more PCI
172 * devices associated with it. The first PCI device that it registers
173 * automatically becomes the default PCI device and can be used implicitly
174 * with the device helper APIs. Subsequent PCI devices must be specified
175 * explicitly to the device helper APIs when used.
176 */
177typedef struct PDMPCIDEV
178{
179 /** @name Read only data.
180 * @{
181 */
182 /** Magic number (PDMPCIDEV_MAGIC). */
183 uint32_t u32Magic;
184 /** PCI device number [11:3] and function [2:0] on the pci bus.
185 * @sa VBOX_PCI_DEVFN_MAKE, VBOX_PCI_DEVFN_FUN_MASK, VBOX_PCI_DEVFN_DEV_SHIFT */
186 uint32_t uDevFn;
187 /** Size of the valid config space (we always allocate 4KB). */
188 uint16_t cbConfig;
189 /** Size of the MSI-X state data optionally following the config space. */
190 uint16_t cbMsixState;
191 /** Index into the PDMDEVINS::apPciDev array. */
192 uint16_t idxSubDev;
193 uint16_t u16Padding;
194 /** Device name. */
195 R3PTRTYPE(const char *) pszNameR3;
196 /** @} */
197
198 /**
199 * Callback for dealing with size changes.
200 *
201 * This is set by the PCI device when needed. It is only needed if any changes
202 * in the PCI resources have been made that may be incompatible with saved state
203 * (i.e. does not reflect configuration, but configuration defaults changed).
204 *
205 * The implementation can use PDMDevHlpMMIOExReduce to adjust the resource
206 * allocation down in size. There is currently no way of growing resources.
207 * Dropping a resource is automatic.
208 *
209 * @returns VBox status code.
210 * @param pDevIns Pointer to the device instance the PCI device
211 * belongs to.
212 * @param pPciDev Pointer to the PCI device.
213 * @param iRegion The region number or UINT32_MAX if old saved state call.
214 * @param cbRegion The size being loaded, RTGCPHYS_MAX if old saved state
215 * call, or 0 for dummy 64-bit top half region.
216 * @param enmType The type being loaded, -1 if old saved state call, or
217 * 0xff if dummy 64-bit top half region.
218 * @param pfnOldSetter Callback for setting size and type for call
219 * regarding old saved states. NULL otherwise.
220 * @param pfnSwapRegions Used to swaps two regions. The second one must be a
221 * higher number than @a iRegion. NULL if old saved
222 * state.
223 */
224 DECLR3CALLBACKMEMBER(int, pfnRegionLoadChangeHookR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
225 uint64_t cbRegion, PCIADDRESSSPACE enmType,
226 PFNPCIIOREGIONOLDSETTER pfnOldSetter,
227 PFNPCIIOREGIONSWAP pfnSwapRegion));
228
229 /** Reserved for future stuff. */
230 uint64_t au64Reserved[4 + (R3_ARCH_BITS == 32 ? 1 : 0)];
231
232 /** Internal data. */
233 union
234 {
235#ifdef PDMPCIDEVINT_DECLARED
236 PDMPCIDEVINT s;
237#endif
238 uint8_t padding[0x180];
239 } Int;
240
241 /** PCI config space.
242 * This is either 256 or 4096 in size. In the latter case it may be
243 * followed by a MSI-X state area. */
244 uint8_t abConfig[4096];
245 /** The MSI-X state data. Optional. */
246 uint8_t abMsixState[RT_FLEXIBLE_ARRAY];
247} PDMPCIDEV;
248#ifdef PDMPCIDEVINT_DECLARED
249AssertCompile(RT_SIZEOFMEMB(PDMPCIDEV, Int.s) <= RT_SIZEOFMEMB(PDMPCIDEV, Int.padding));
250#endif
251/** Magic number of PDMPCIDEV::u32Magic (Margaret Eleanor Atwood). */
252#define PDMPCIDEV_MAGIC UINT32_C(0x19391118)
253
254/** Checks that the PCI device structure is valid and belongs to the device
255 * instance, but does not return. */
256#ifdef VBOX_STRICT
257# define PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev) \
258 do { \
259 uintptr_t const offPciDevInTable = (uintptr_t)(a_pPciDev) - (uintptr_t)pDevIns->apPciDevs[0]; \
260 uint32_t const cbPciDevTmp = pDevIns->cbPciDev; \
261 ASMCompilerBarrier(); \
262 AssertMsg( offPciDevInTable < pDevIns->cPciDevs * cbPciDevTmp \
263 && cbPciDevTmp >= RT_UOFFSETOF(PDMPCIDEV, abConfig) + 256 \
264 && offPciDevInTable % cbPciDevTmp == 0, \
265 ("pPciDev=%p apPciDevs[0]=%p offPciDevInTable=%p cPciDevs=%#x cbPciDev=%#x\n", \
266 (a_pPciDev), pDevIns->apPciDevs[0], offPciDevInTable, pDevIns->cPciDevs, cbPciDevTmp)); \
267 AssertPtr((a_pPciDev)); \
268 AssertMsg((a_pPciDev)->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", (a_pPciDev)->u32Magic)); \
269 } while (0)
270#else
271# define PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev) do { } while (0)
272#endif
273
274/** Checks that the PCI device structure is valid, belongs to the device
275 * instance and that it is registered, but does not return. */
276#ifdef VBOX_STRICT
277# define PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(a_pDevIns, a_pPciDev) \
278 do { \
279 PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev); \
280 Assert((a_pPciDev)->Int.s.fRegistered); \
281 } while (0)
282#else
283# define PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(a_pDevIns, a_pPciDev) do { } while (0)
284#endif
285
286/** Checks that the PCI device structure is valid and belongs to the device
287 * instance, returns appropriate status code if not valid. */
288#define PDMPCIDEV_ASSERT_VALID_RET(a_pDevIns, a_pPciDev) \
289 do { \
290 uintptr_t const offPciDevInTable = (uintptr_t)(a_pPciDev) - (uintptr_t)pDevIns->apPciDevs[0]; \
291 uint32_t const cbPciDevTmp = pDevIns->cbPciDev; \
292 ASMCompilerBarrier(); \
293 AssertMsgReturn( offPciDevInTable < pDevIns->cPciDevs * cbPciDevTmp \
294 && cbPciDevTmp >= RT_UOFFSETOF(PDMPCIDEV, abConfig) + 256 \
295 && offPciDevInTable % cbPciDevTmp == 0, \
296 ("pPciDev=%p apPciDevs[0]=%p offPciDevInTable=%p cPciDevs=%#x cbPciDev=%#x\n", \
297 (a_pPciDev), pDevIns->apPciDevs[0], offPciDevInTable, pDevIns->cPciDevs, cbPciDevTmp), \
298 VERR_PDM_NOT_PCI_DEVICE); \
299 AssertMsgReturn((a_pPciDev)->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", (a_pPciDev)->u32Magic), VERR_PDM_NOT_PCI_DEVICE); \
300 AssertReturn((a_pPciDev)->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE); \
301 } while (0)
302
303
304
305/** @name PDM PCI config space accessor function.
306 * @{
307 */
308
309/** @todo handle extended space access. */
310
311DECLINLINE(void) PDMPciDevSetByte(PPDMPCIDEV pPciDev, uint32_t offReg, uint8_t u8Value)
312{
313 Assert(offReg < sizeof(pPciDev->abConfig));
314 pPciDev->abConfig[offReg] = u8Value;
315}
316
317DECLINLINE(uint8_t) PDMPciDevGetByte(PCPDMPCIDEV pPciDev, uint32_t offReg)
318{
319 Assert(offReg < sizeof(pPciDev->abConfig));
320 return pPciDev->abConfig[offReg];
321}
322
323DECLINLINE(void) PDMPciDevSetWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint16_t u16Value)
324{
325 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint16_t));
326 *(uint16_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U16(u16Value);
327}
328
329DECLINLINE(uint16_t) PDMPciDevGetWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
330{
331 uint16_t u16Value;
332 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint16_t));
333 u16Value = *(uint16_t*)&pPciDev->abConfig[offReg];
334 return RT_H2LE_U16(u16Value);
335}
336
337DECLINLINE(void) PDMPciDevSetDWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint32_t u32Value)
338{
339 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint32_t));
340 *(uint32_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U32(u32Value);
341}
342
343DECLINLINE(uint32_t) PDMPciDevGetDWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
344{
345 uint32_t u32Value;
346 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint32_t));
347 u32Value = *(uint32_t*)&pPciDev->abConfig[offReg];
348 return RT_H2LE_U32(u32Value);
349}
350
351DECLINLINE(void) PDMPciDevSetQWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint64_t u64Value)
352{
353 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint64_t));
354 *(uint64_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U64(u64Value);
355}
356
357DECLINLINE(uint64_t) PDMPciDevGetQWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
358{
359 uint64_t u64Value;
360 Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint64_t));
361 u64Value = *(uint64_t*)&pPciDev->abConfig[offReg];
362 return RT_H2LE_U64(u64Value);
363}
364
365/**
366 * Sets the vendor id config register.
367 * @param pPciDev The PCI device.
368 * @param u16VendorId The vendor id.
369 */
370DECLINLINE(void) PDMPciDevSetVendorId(PPDMPCIDEV pPciDev, uint16_t u16VendorId)
371{
372 PDMPciDevSetWord(pPciDev, VBOX_PCI_VENDOR_ID, u16VendorId);
373}
374
375/**
376 * Gets the vendor id config register.
377 * @returns the vendor id.
378 * @param pPciDev The PCI device.
379 */
380DECLINLINE(uint16_t) PDMPciDevGetVendorId(PCPDMPCIDEV pPciDev)
381{
382 return PDMPciDevGetWord(pPciDev, VBOX_PCI_VENDOR_ID);
383}
384
385
386/**
387 * Sets the device id config register.
388 * @param pPciDev The PCI device.
389 * @param u16DeviceId The device id.
390 */
391DECLINLINE(void) PDMPciDevSetDeviceId(PPDMPCIDEV pPciDev, uint16_t u16DeviceId)
392{
393 PDMPciDevSetWord(pPciDev, VBOX_PCI_DEVICE_ID, u16DeviceId);
394}
395
396/**
397 * Gets the device id config register.
398 * @returns the device id.
399 * @param pPciDev The PCI device.
400 */
401DECLINLINE(uint16_t) PDMPciDevGetDeviceId(PCPDMPCIDEV pPciDev)
402{
403 return PDMPciDevGetWord(pPciDev, VBOX_PCI_DEVICE_ID);
404}
405
406/**
407 * Sets the command config register.
408 *
409 * @param pPciDev The PCI device.
410 * @param u16Command The command register value.
411 */
412DECLINLINE(void) PDMPciDevSetCommand(PPDMPCIDEV pPciDev, uint16_t u16Command)
413{
414 PDMPciDevSetWord(pPciDev, VBOX_PCI_COMMAND, u16Command);
415}
416
417
418/**
419 * Gets the command config register.
420 * @returns The command register value.
421 * @param pPciDev The PCI device.
422 */
423DECLINLINE(uint16_t) PDMPciDevGetCommand(PCPDMPCIDEV pPciDev)
424{
425 return PDMPciDevGetWord(pPciDev, VBOX_PCI_COMMAND);
426}
427
428/**
429 * Checks if the given PCI device is a bus master.
430 * @returns true if the device is a bus master, false if not.
431 * @param pPciDev The PCI device.
432 */
433DECLINLINE(bool) PDMPciDevIsBusmaster(PCPDMPCIDEV pPciDev)
434{
435 return (PDMPciDevGetCommand(pPciDev) & VBOX_PCI_COMMAND_MASTER) != 0;
436}
437
438/**
439 * Checks if INTx interrupts disabled in the command config register.
440 * @returns true if disabled.
441 * @param pPciDev The PCI device.
442 */
443DECLINLINE(bool) PDMPciDevIsIntxDisabled(PCPDMPCIDEV pPciDev)
444{
445 return (PDMPciDevGetCommand(pPciDev) & VBOX_PCI_COMMAND_INTX_DISABLE) != 0;
446}
447
448/**
449 * Gets the status config register.
450 *
451 * @returns status config register.
452 * @param pPciDev The PCI device.
453 */
454DECLINLINE(uint16_t) PDMPciDevGetStatus(PCPDMPCIDEV pPciDev)
455{
456 return PDMPciDevGetWord(pPciDev, VBOX_PCI_STATUS);
457}
458
459/**
460 * Sets the status config register.
461 *
462 * @param pPciDev The PCI device.
463 * @param u16Status The status register value.
464 */
465DECLINLINE(void) PDMPciDevSetStatus(PPDMPCIDEV pPciDev, uint16_t u16Status)
466{
467 PDMPciDevSetWord(pPciDev, VBOX_PCI_STATUS, u16Status);
468}
469
470
471/**
472 * Sets the revision id config register.
473 *
474 * @param pPciDev The PCI device.
475 * @param u8RevisionId The revision id.
476 */
477DECLINLINE(void) PDMPciDevSetRevisionId(PPDMPCIDEV pPciDev, uint8_t u8RevisionId)
478{
479 PDMPciDevSetByte(pPciDev, VBOX_PCI_REVISION_ID, u8RevisionId);
480}
481
482
483/**
484 * Sets the register level programming class config register.
485 *
486 * @param pPciDev The PCI device.
487 * @param u8ClassProg The new value.
488 */
489DECLINLINE(void) PDMPciDevSetClassProg(PPDMPCIDEV pPciDev, uint8_t u8ClassProg)
490{
491 PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_PROG, u8ClassProg);
492}
493
494
495/**
496 * Sets the sub-class (aka device class) config register.
497 *
498 * @param pPciDev The PCI device.
499 * @param u8SubClass The sub-class.
500 */
501DECLINLINE(void) PDMPciDevSetClassSub(PPDMPCIDEV pPciDev, uint8_t u8SubClass)
502{
503 PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_SUB, u8SubClass);
504}
505
506
507/**
508 * Sets the base class config register.
509 *
510 * @param pPciDev The PCI device.
511 * @param u8BaseClass The base class.
512 */
513DECLINLINE(void) PDMPciDevSetClassBase(PPDMPCIDEV pPciDev, uint8_t u8BaseClass)
514{
515 PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_BASE, u8BaseClass);
516}
517
518/**
519 * Sets the header type config register.
520 *
521 * @param pPciDev The PCI device.
522 * @param u8HdrType The header type.
523 */
524DECLINLINE(void) PDMPciDevSetHeaderType(PPDMPCIDEV pPciDev, uint8_t u8HdrType)
525{
526 PDMPciDevSetByte(pPciDev, VBOX_PCI_HEADER_TYPE, u8HdrType);
527}
528
529/**
530 * Gets the header type config register.
531 *
532 * @param pPciDev The PCI device.
533 * @returns u8HdrType The header type.
534 */
535DECLINLINE(uint8_t) PDMPciDevGetHeaderType(PCPDMPCIDEV pPciDev)
536{
537 return PDMPciDevGetByte(pPciDev, VBOX_PCI_HEADER_TYPE);
538}
539
540/**
541 * Sets the BIST (built-in self-test) config register.
542 *
543 * @param pPciDev The PCI device.
544 * @param u8Bist The BIST value.
545 */
546DECLINLINE(void) PDMPciDevSetBIST(PPDMPCIDEV pPciDev, uint8_t u8Bist)
547{
548 PDMPciDevSetByte(pPciDev, VBOX_PCI_BIST, u8Bist);
549}
550
551/**
552 * Gets the BIST (built-in self-test) config register.
553 *
554 * @param pPciDev The PCI device.
555 * @returns u8Bist The BIST.
556 */
557DECLINLINE(uint8_t) PDMPciDevGetBIST(PCPDMPCIDEV pPciDev)
558{
559 return PDMPciDevGetByte(pPciDev, VBOX_PCI_BIST);
560}
561
562
563/**
564 * Sets a base address config register.
565 *
566 * @param pPciDev The PCI device.
567 * @param iReg Base address register number (0..5).
568 * @param fIOSpace Whether it's I/O (true) or memory (false) space.
569 * @param fPrefetchable Whether the memory is prefetachable. Must be false if fIOSpace == true.
570 * @param f64Bit Whether the memory can be mapped anywhere in the 64-bit address space. Otherwise restrict to 32-bit.
571 * @param u32Addr The address value.
572 */
573DECLINLINE(void) PDMPciDevSetBaseAddress(PPDMPCIDEV pPciDev, uint8_t iReg, bool fIOSpace, bool fPrefetchable, bool f64Bit,
574 uint32_t u32Addr)
575{
576 if (fIOSpace)
577 {
578 Assert(!(u32Addr & 0x3)); Assert(!fPrefetchable); Assert(!f64Bit);
579 u32Addr |= RT_BIT_32(0);
580 }
581 else
582 {
583 Assert(!(u32Addr & 0xf));
584 if (fPrefetchable)
585 u32Addr |= RT_BIT_32(3);
586 if (f64Bit)
587 u32Addr |= 0x2 << 1;
588 }
589 switch (iReg)
590 {
591 case 0: iReg = VBOX_PCI_BASE_ADDRESS_0; break;
592 case 1: iReg = VBOX_PCI_BASE_ADDRESS_1; break;
593 case 2: iReg = VBOX_PCI_BASE_ADDRESS_2; break;
594 case 3: iReg = VBOX_PCI_BASE_ADDRESS_3; break;
595 case 4: iReg = VBOX_PCI_BASE_ADDRESS_4; break;
596 case 5: iReg = VBOX_PCI_BASE_ADDRESS_5; break;
597 default: AssertFailedReturnVoid();
598 }
599
600 PDMPciDevSetDWord(pPciDev, iReg, u32Addr);
601}
602
603/**
604 * Please document me. I don't seem to be getting as much as calculating
605 * the address of some PCI region.
606 */
607DECLINLINE(uint32_t) PDMPciDevGetRegionReg(uint32_t iRegion)
608{
609 return iRegion == VBOX_PCI_ROM_SLOT
610 ? VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
611}
612
613/**
614 * Sets the sub-system vendor id config register.
615 *
616 * @param pPciDev The PCI device.
617 * @param u16SubSysVendorId The sub-system vendor id.
618 */
619DECLINLINE(void) PDMPciDevSetSubSystemVendorId(PPDMPCIDEV pPciDev, uint16_t u16SubSysVendorId)
620{
621 PDMPciDevSetWord(pPciDev, VBOX_PCI_SUBSYSTEM_VENDOR_ID, u16SubSysVendorId);
622}
623
624/**
625 * Gets the sub-system vendor id config register.
626 * @returns the sub-system vendor id.
627 * @param pPciDev The PCI device.
628 */
629DECLINLINE(uint16_t) PDMPciDevGetSubSystemVendorId(PCPDMPCIDEV pPciDev)
630{
631 return PDMPciDevGetWord(pPciDev, VBOX_PCI_SUBSYSTEM_VENDOR_ID);
632}
633
634
635/**
636 * Sets the sub-system id config register.
637 *
638 * @param pPciDev The PCI device.
639 * @param u16SubSystemId The sub-system id.
640 */
641DECLINLINE(void) PDMPciDevSetSubSystemId(PPDMPCIDEV pPciDev, uint16_t u16SubSystemId)
642{
643 PDMPciDevSetWord(pPciDev, VBOX_PCI_SUBSYSTEM_ID, u16SubSystemId);
644}
645
646/**
647 * Gets the sub-system id config register.
648 * @returns the sub-system id.
649 * @param pPciDev The PCI device.
650 */
651DECLINLINE(uint16_t) PDMPciDevGetSubSystemId(PCPDMPCIDEV pPciDev)
652{
653 return PDMPciDevGetWord(pPciDev, VBOX_PCI_SUBSYSTEM_ID);
654}
655
656/**
657 * Sets offset to capability list.
658 *
659 * @param pPciDev The PCI device.
660 * @param u8Offset The offset to capability list.
661 */
662DECLINLINE(void) PDMPciDevSetCapabilityList(PPDMPCIDEV pPciDev, uint8_t u8Offset)
663{
664 PDMPciDevSetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST, u8Offset);
665}
666
667/**
668 * Returns offset to capability list.
669 *
670 * @returns offset to capability list.
671 * @param pPciDev The PCI device.
672 */
673DECLINLINE(uint8_t) PDMPciDevGetCapabilityList(PCPDMPCIDEV pPciDev)
674{
675 return PDMPciDevGetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST);
676}
677
678/**
679 * Sets the interrupt line config register.
680 *
681 * @param pPciDev The PCI device.
682 * @param u8Line The interrupt line.
683 */
684DECLINLINE(void) PDMPciDevSetInterruptLine(PPDMPCIDEV pPciDev, uint8_t u8Line)
685{
686 PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE, u8Line);
687}
688
689/**
690 * Gets the interrupt line config register.
691 *
692 * @returns The interrupt line.
693 * @param pPciDev The PCI device.
694 */
695DECLINLINE(uint8_t) PDMPciDevGetInterruptLine(PCPDMPCIDEV pPciDev)
696{
697 return PDMPciDevGetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE);
698}
699
700/**
701 * Sets the interrupt pin config register.
702 *
703 * @param pPciDev The PCI device.
704 * @param u8Pin The interrupt pin.
705 */
706DECLINLINE(void) PDMPciDevSetInterruptPin(PPDMPCIDEV pPciDev, uint8_t u8Pin)
707{
708 PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN, u8Pin);
709}
710
711/**
712 * Gets the interrupt pin config register.
713 *
714 * @returns The interrupt pin.
715 * @param pPciDev The PCI device.
716 */
717DECLINLINE(uint8_t) PDMPciDevGetInterruptPin(PCPDMPCIDEV pPciDev)
718{
719 return PDMPciDevGetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN);
720}
721
722/** @} */
723
724/** @name Aliases for old function names.
725 * @{
726 */
727#if !defined(PDMPCIDEVICE_NO_DEPRECATED) || defined(DOXYGEN_RUNNING)
728# define PCIDevSetByte PDMPciDevSetByte
729# define PCIDevGetByte PDMPciDevGetByte
730# define PCIDevSetWord PDMPciDevSetWord
731# define PCIDevGetWord PDMPciDevGetWord
732# define PCIDevSetDWord PDMPciDevSetDWord
733# define PCIDevGetDWord PDMPciDevGetDWord
734# define PCIDevSetQWord PDMPciDevSetQWord
735# define PCIDevGetQWord PDMPciDevGetQWord
736# define PCIDevSetVendorId PDMPciDevSetVendorId
737# define PCIDevGetVendorId PDMPciDevGetVendorId
738# define PCIDevSetDeviceId PDMPciDevSetDeviceId
739# define PCIDevGetDeviceId PDMPciDevGetDeviceId
740# define PCIDevSetCommand PDMPciDevSetCommand
741# define PCIDevGetCommand PDMPciDevGetCommand
742# define PCIDevIsBusmaster PDMPciDevIsBusmaster
743# define PCIDevIsIntxDisabled PDMPciDevIsIntxDisabled
744# define PCIDevGetStatus PDMPciDevGetStatus
745# define PCIDevSetStatus PDMPciDevSetStatus
746# define PCIDevSetRevisionId PDMPciDevSetRevisionId
747# define PCIDevSetClassProg PDMPciDevSetClassProg
748# define PCIDevSetClassSub PDMPciDevSetClassSub
749# define PCIDevSetClassBase PDMPciDevSetClassBase
750# define PCIDevSetHeaderType PDMPciDevSetHeaderType
751# define PCIDevGetHeaderType PDMPciDevGetHeaderType
752# define PCIDevSetBIST PDMPciDevSetBIST
753# define PCIDevGetBIST PDMPciDevGetBIST
754# define PCIDevSetBaseAddress PDMPciDevSetBaseAddress
755# define PCIDevGetRegionReg PDMPciDevGetRegionReg
756# define PCIDevSetSubSystemVendorId PDMPciDevSetSubSystemVendorId
757# define PCIDevGetSubSystemVendorId PDMPciDevGetSubSystemVendorId
758# define PCIDevSetSubSystemId PDMPciDevSetSubSystemId
759# define PCIDevGetSubSystemId PDMPciDevGetSubSystemId
760# define PCIDevSetCapabilityList PDMPciDevSetCapabilityList
761# define PCIDevGetCapabilityList PDMPciDevGetCapabilityList
762# define PCIDevSetInterruptLine PDMPciDevSetInterruptLine
763# define PCIDevGetInterruptLine PDMPciDevGetInterruptLine
764# define PCIDevSetInterruptPin PDMPciDevSetInterruptPin
765# define PCIDevGetInterruptPin PDMPciDevGetInterruptPin
766#endif
767/** @} */
768
769
770/** @name PDMIICH9BRIDGEPDMPCIDEV_IID - Ugly 3rd party bridge/raw PCI hack.
771 *
772 * When querying this IID via IBase::pfnQueryInterface on a ICH9 bridge, you
773 * will get a pointer to a PDMPCIDEV rather pointer to an interface function
774 * table as is the custom. This was needed by some unusual 3rd-party raw and/or
775 * pass-through implementation which need to provide different PCI configuration
776 * space content for bridges (as long as we don't allow pass-through of bridges
777 * or custom bridge device implementations). So, HACK ALERT to all of this!
778 * @{ */
779#define PDMIICH9BRIDGEPDMPCIDEV_IID "785c74b1-8510-4458-9422-56750bf221db"
780typedef PPDMPCIDEV PPDMIICH9BRIDGEPDMPCIDEV;
781typedef PDMPCIDEV PDMIICH9BRIDGEPDMPCIDEV;
782/** @} */
783
784
785/** @} */
786
787#endif /* !VBOX_INCLUDED_vmm_pdmpcidev_h */
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