ReactOS 0.4.17-dev-1133-gc25e4fd
rbar.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: PCI Express Resizable BAR Support
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <pci.h>
11
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
17#define PCI_RBAR_SIZE_TO_LENGTH(Bit) (1ULL << ((Bit) + 20))
18
19/* FUNCTIONS ******************************************************************/
20
29VOID
33{
34 PPCI_RESIZABLE_BAR_STATE State = &PdoExtension->ResizableBarState;
36 ULONG Offset, Entry, EntryCount, Control, SizeMask, BarIndex;
37
38 PAGED_CODE();
39
40 RtlZeroMemory(State, sizeof(*State));
41
42 /* Bridges keep their windows after the first two BARs, so only endpoints are resized */
43 if (PdoExtension->HeaderType != PCI_DEVICE_TYPE)
44 return;
45
48 &Header,
49 sizeof(Header));
50 if (!Offset)
51 return;
52
53 /* Only the first control register holds the number of entries */
55 &Control,
57 sizeof(Control));
59 if (EntryCount > PCI_RBAR_MAX_ENTRIES)
60 EntryCount = PCI_RBAR_MAX_ENTRIES;
61
62 State->CapabilityPtr = (USHORT)Offset;
63
64 for (Entry = 0; Entry < EntryCount; Entry++)
65 {
67 &SizeMask,
69 sizeof(SizeMask));
71 &Control,
73 sizeof(Control));
74
77
78 /* Skip entries with no sizes, a BAR that cannot exist, or a BAR already seen */
79 if (!SizeMask ||
80 (BarIndex >= PCI_RBAR_MAX_ENTRIES) ||
81 State->SizeMask[BarIndex])
82 {
83 continue;
84 }
85
86 State->SizeMask[BarIndex] = SizeMask;
87 State->EntryIndex[BarIndex] = (UCHAR)Entry;
88
89 DPRINT1("PCI: BAR %lu of %p is resizable, sizes 0x%08lx\n",
90 BarIndex, PdoExtension, SizeMask);
91 }
92}
93
94static
101 _In_ UCHAR Option)
102{
104
105 *Descriptor = *Limit;
106 Descriptor->Option = Option;
107 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
108
111 Length,
112 Length,
113 Limit->u.Memory.MinimumAddress.QuadPart,
114 Limit->u.Memory.MaximumAddress.QuadPart);
115 return NT_SUCCESS(Status);
116}
117
140ULONG
141NTAPI
144 _In_ ULONG BarIndex,
147{
148 IO_RESOURCE_DESCRIPTOR Resized[2];
149 ULONGLONG Largest, Smallest;
150 ULONG SizeMask, Count;
151 PAGED_CODE();
152
153 /* Only a memory BAR asking for less than 4GB is offered other sizes */
154 if ((BarIndex >= PCI_RBAR_MAX_ENTRIES) || (Limit->Type != CmResourceTypeMemory))
155 return 0;
156
157 SizeMask = PdoExtension->ResizableBarState.SizeMask[BarIndex];
158 if (!SizeMask)
159 return 0;
160
161 /* Built even when only counting, so a size that cannot be described is never counted */
163 if ((Largest <= Limit->u.Memory.Length) ||
165 {
166 return 0;
167 }
168 Count = 1;
169
171 if ((Smallest > Limit->u.Memory.Length) &&
172 (Smallest < Largest) &&
174 {
175 Count++;
176 }
177
178 if (Descriptors)
179 RtlCopyMemory(Descriptors, Resized, Count * sizeof(IO_RESOURCE_DESCRIPTOR));
180
181 return Count;
182}
183
184static
185VOID
186NTAPI
189 _In_ ULONG BarIndex,
191{
192 PPCI_RESIZABLE_BAR_STATE State = &PdoExtension->ResizableBarState;
193 ULONGLONG Megabytes;
194 ULONG SizeBit, Control, Offset;
195
196 /* Only a power of two of at least a megabyte can be specified in the size field */
197 Megabytes = Length >> 20;
198 if (!Megabytes || (Megabytes & (Megabytes - 1)) || (Length & 0xFFFFF))
199 return;
200
201 if (!(State->SizeMask[BarIndex] & Megabytes))
202 return;
203
204 SizeBit = (ULONG)RtlFindMostSignificantBit(Megabytes);
205
206 Offset = State->CapabilityPtr + PCI_RBAR_ENTRY_CONTROL(State->EntryIndex[BarIndex]);
209 return;
210
211 Control &= ~PCI_RBAR_CONTROL_SIZE_MASK;
214
215 DPRINT("PCI: BAR %lu of %p resized to %I64u MB\n", BarIndex, PdoExtension, Megabytes);
216}
217
227VOID
228NTAPI
231{
234 ULONG BarIndex;
235
236 if (!PdoExtension->ResizableBarState.CapabilityPtr || !PdoExtension->Resources)
237 return;
238
239 /* A function whose decodes could not be turned off keeps the sizes it has */
241 &Command,
243 sizeof(Command));
245 {
246 DPRINT("PCI: Memory decode of %p is still on, not resizing BARs\n", PdoExtension);
247 return;
248 }
249
250 for (BarIndex = 0; BarIndex < PCI_RBAR_MAX_ENTRIES; BarIndex++)
251 {
252 if (!PdoExtension->ResizableBarState.SizeMask[BarIndex])
253 continue;
254
255 Current = &PdoExtension->Resources->Current[BarIndex];
256 if ((Current->Type != CmResourceTypeMemory) &&
257 (Current->Type != CmResourceTypeMemoryLarge))
258 {
259 continue;
260 }
261
263 BarIndex,
265 }
266}
267
268/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
ULONGLONG NTAPI RtlCmDecodeMemIoResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, _Out_opt_ PULONGLONG Start)
Definition: memres.c:58
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
VOID NTAPI PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:133
#define PCI_RBAR_CONTROL_SIZE_SHIFT
Definition: pci.h:91
#define PCI_RBAR_CONTROL_SIZE_MASK
Definition: pci.h:90
#define PCI_RBAR_CONTROL_BAR_INDEX_MASK
Definition: pci.h:87
#define PCI_RBAR_ENTRY_CONTROL(n)
Definition: pci.h:85
#define PCI_RBAR_CAPABILITY_SIZES_SHIFT
Definition: pci.h:86
#define PCI_RBAR_ENTRY_CAPABILITY(n)
Definition: pci.h:84
#define PCI_RBAR_CONTROL_COUNT_SHIFT
Definition: pci.h:89
#define PCI_RBAR_MAX_ENTRIES
Definition: pci.h:83
#define PCI_RBAR_CONTROL_COUNT_MASK
Definition: pci.h:88
#define PCI_RBAR_EXTENDED_CAP_ID
Definition: pci.h:82
VOID NTAPI PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:149
ULONG NTAPI PciReadDeviceExtendedCapability(_In_ PPCI_PDO_EXTENSION DeviceExtension, _In_ ULONG CapabilityId, _Out_writes_bytes_(Length) PPCI_EXPRESS_ENHANCED_CAPABILITY_HEADER Buffer, _In_ ULONG Length)
Finds an extended capability and reads it into the caller's buffer.
Definition: express.c:39
@ PdoExtension
Definition: precomp.h:61
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_opt_(s)
Definition: no_sal2.h:226
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
static BOOLEAN NTAPI PciFillResizedBarRequirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor, _In_ PIO_RESOURCE_DESCRIPTOR Limit, _In_ ULONGLONG Length, _In_ UCHAR Option)
Definition: rbar.c:97
VOID NTAPI PciApplyResizableBarSizes(_In_ PPCI_PDO_EXTENSION PdoExtension)
Sets every resizable BAR to the length it was assigned. The memory decode has to be off,...
Definition: rbar.c:229
ULONG NTAPI PciAddResizableBarRequirements(_In_ PPCI_PDO_EXTENSION PdoExtension, _In_ ULONG BarIndex, _In_ PIO_RESOURCE_DESCRIPTOR Limit, _Out_writes_opt_(2) PIO_RESOURCE_DESCRIPTOR Descriptors)
Writes the requirements for the sizes a resizable BAR can grow to. They go ahead of the default requi...
Definition: rbar.c:142
VOID NTAPI PciGetResizableBarCapability(_Inout_ PPCI_PDO_EXTENSION PdoExtension)
Records which BARs of a new function can be resized and the sizes each of them supports.
Definition: rbar.c:31
static VOID NTAPI PciSelectResizableBarSize(_In_ PPCI_PDO_EXTENSION PdoExtension, _In_ ULONG BarIndex, _In_ ULONGLONG Length)
Definition: rbar.c:187
#define PCI_RBAR_SIZE_TO_LENGTH(Bit)
Definition: rbar.c:17
#define CmResourceTypeMemory
Definition: restypes.h:106
Entry
Definition: section.c:5216
#define DPRINT
Definition: sndvol32.h:73
Definition: shell.h:41
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
uint64_t ULONGLONG
Definition: typedefs.h:67
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
NTSYSAPI CCHAR WINAPI RtlFindMostSignificantBit(ULONGLONG)
Definition: bitmap.c:211
NTSYSAPI CCHAR WINAPI RtlFindLeastSignificantBit(ULONGLONG)
Definition: bitmap.c:235
@ CmResourceShareDeviceExclusive
Definition: cmtypes.h:241
#define CmResourceTypeMemoryLarge
Definition: cmtypes.h:231
#define IO_RESOURCE_ALTERNATIVE
#define PCI_ENABLE_MEMORY_SPACE
Definition: iotypes.h:3619
#define IO_RESOURCE_PREFERRED
#define PCI_DEVICE_TYPE
Definition: iotypes.h:3607
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304
NTSYSAPI NTSTATUS NTAPI RtlIoEncodeMemIoResource(_In_ struct _IO_RESOURCE_DESCRIPTOR *Descriptor, _In_ UCHAR Type, _In_ ULONGLONG Length, _In_ ULONGLONG Alignment, _In_ ULONGLONG MinimumAddress, _In_ ULONGLONG MaximumAddress)