VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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