ReactOS 0.4.17-dev-966-gf06eace
device.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/device.c
5 * PURPOSE: Device Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <pci.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* FUNCTIONS ******************************************************************/
17
18VOID
21{
22 PPCI_COMMON_HEADER PciData;
23 PIO_RESOURCE_DESCRIPTOR IoDescriptor;
26 PULONG BarArray;
27 ULONG Bar, BarMask, i;
28
29 /* Get variables from context */
30 PciData = Context->Current;
31 Resources = Context->PdoExtension->Resources;
32
33 /* Loop all the PCI BARs */
34 BarArray = PciData->u.type0.BaseAddresses;
35 for (i = 0; i <= PCI_TYPE0_ADDRESSES; i++)
36 {
37 /* Get the resource descriptor and limit descriptor for this BAR */
38 CmDescriptor = &Resources->Current[i];
39 IoDescriptor = &Resources->Limit[i];
40
41 /* Build the resource descriptor based on the limit descriptor */
42 CmDescriptor->Type = IoDescriptor->Type;
43 if (CmDescriptor->Type == CmResourceTypeNull) continue;
44 CmDescriptor->Flags = IoDescriptor->Flags;
45 CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
46 CmDescriptor->u.Generic.Start.HighPart = 0;
47 CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
48
49 /* Check if we're handling PCI BARs, or the ROM BAR */
51 {
52 /* Read the actual BAR value */
53 Bar = BarArray[i];
54
55 /* Check if this is an I/O BAR */
57 {
58 /* Use the right mask to get the I/O port base address */
59 ASSERT(CmDescriptor->Type == CmResourceTypePort);
61 }
62 else
63 {
64 /* It's a RAM BAR, use the right mask to get the base address */
65 ASSERT((CmDescriptor->Type == CmResourceTypeMemory) ||
66 (CmDescriptor->Type == CmResourceTypeMemoryLarge));
68
69 /* Check if it's a 64-bit BAR */
71 {
72 /* The next BAR value is actually the high 32-bits */
73 CmDescriptor->u.Memory.Start.HighPart = BarArray[i + 1];
74 }
76 {
77 /* Legacy BAR, don't read more than 20 bits of the address */
78 BarMask = 0xFFFF0;
79 }
80 }
81 }
82 else
83 {
84 /* Actually a ROM BAR, so read the correct register */
85 Bar = PciData->u.type0.ROMBaseAddress;
86
87 /* Apply the correct mask for ROM BARs */
89
90 /* Make sure it's enabled */
92 {
93 /* If it isn't, then a descriptor won't be built for it */
94 CmDescriptor->Type = CmResourceTypeNull;
95 continue;
96 }
97 }
98
99 /* Now we have the right mask, read the actual address from the BAR */
100 Bar &= BarMask;
101 CmDescriptor->u.Memory.Start.LowPart = Bar;
102
103 /* And check for invalid BAR addresses */
104 if (!(CmDescriptor->u.Memory.Start.HighPart | Bar))
105 {
106 /* Skip these descriptors */
107 CmDescriptor->Type = CmResourceTypeNull;
108 DPRINT1("Invalid BAR\n");
109 }
110 }
111
112 /* Also save the sub-IDs that came directly from the PCI header */
113 Context->PdoExtension->SubsystemVendorId = PciData->u.type0.SubVendorID;
114 Context->PdoExtension->SubsystemId = PciData->u.type0.SubSystemID;
115}
116
117VOID
118NTAPI
120{
121 PPCI_COMMON_HEADER Current, PciData;
123 PULONG BarArray;
125 ULONG i;
126
127 /* Get pointers from the context */
128 PdoExtension = Context->PdoExtension;
129 Current = Context->Current;
130 PciData = Context->PciData;
131
132 /* And get the array of bARs */
133 BarArray = PciData->u.type0.BaseAddresses;
134
135 /* First, check for IDE controllers that are not in native mode */
136 if ((PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
138 (PdoExtension->ProgIf & 5) != 5)
139 {
140 /* They should not be using any non-legacy resources */
141 BarArray[0] = 0;
142 BarArray[1] = 0;
143 BarArray[2] = 0;
144 BarArray[3] = 0;
145 }
146 else if ((PdoExtension->VendorId == 0x5333) &&
147 ((PdoExtension->DeviceId == 0x88F0) ||
148 (PdoExtension->DeviceId == 0x8880)))
149 {
150 /*
151 * The problem is caused by the S3 Vision 968/868 video controller which
152 * is used on the Diamond Stealth 64 Video 3000 series, Number Nine 9FX
153 * motion 771, and other popular video cards, all containing a memory bug.
154 * The 968/868 claims to require 32 MB of memory, but it actually decodes
155 * 64 MB of memory.
156 */
157 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
158 {
159 /* Find its 32MB RAM BAR */
160 if (BarArray[i] == 0xFE000000)
161 {
162 /* Increase it to 64MB to make sure nobody touches the buffer */
163 BarArray[i] = 0xFC000000;
164 DPRINT1("PCI - Adjusted broken S3 requirement from 32MB to 64MB\n");
165 }
166 }
167 }
168
169 /* Check for Cirrus Logic GD5430/5440 cards */
170 if ((PdoExtension->VendorId == 0x1013) && (PdoExtension->DeviceId == 0xA0))
171 {
172 /* Check for the I/O port requirement */
173 if (BarArray[1] == 0xFC01)
174 {
175 /* Check for completely bogus BAR */
176 if (Current->u.type0.BaseAddresses[1] == 1)
177 {
178 /* Ignore it */
179 BarArray[1] = 0;
180 DPRINT1("PCI - Ignored Cirrus GD54xx broken IO requirement (400 ports)\n");
181 }
182 else
183 {
184 /* Otherwise, this BAR seems okay */
185 DPRINT1("PCI - Cirrus GD54xx 400 port IO requirement has a valid setting (%08x)\n",
186 Current->u.type0.BaseAddresses[1]);
187 }
188 }
189 else if (BarArray[1])
190 {
191 /* Strange, the I/O BAR was not found as expected (or at all) */
192 DPRINT1("PCI - Warning Cirrus Adapter 101300a0 has unexpected resource requirement (%08x)\n",
193 BarArray[1]);
194 }
195 }
196
197 /* Finally, process all the limit descriptors */
198 Limit = PdoExtension->Resources->Limit;
199 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
200 {
201 /* And build them based on the BARs, the last one has no BAR after it for a high half */
202 ULONG NextBar = ((i + 1) < PCI_TYPE0_ADDRESSES) ? BarArray[i + 1] : 0;
203
204 if (PciCreateIoDescriptorFromBarLimit(&Limit[i], BarArray[i], NextBar, FALSE))
205 {
206 /* This function returns TRUE if the BAR was 64-bit, handle this */
208 i++;
209 Limit[i].Type = CmResourceTypeNull;
210 }
211 }
212
213 /* Create the last descriptor based on the ROM address */
214 PciCreateIoDescriptorFromBarLimit(&Limit[i], PciData->u.type0.ROMBaseAddress, 0, TRUE);
215}
216
217VOID
218NTAPI
220{
221 PPCI_COMMON_HEADER PciData;
223 PULONG BarArray;
224 ULONG i = 0;
225
226 /* Get pointers from context data */
227 PdoExtension = Context->PdoExtension;
228 PciData = Context->PciData;
229
230 /* Get the array of BARs */
231 BarArray = PciData->u.type0.BaseAddresses;
232
233 /* Check for IDE controllers that are not in native mode */
234 if ((PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
236 (PdoExtension->ProgIf & 5) != 5)
237 {
238 /* These controllers only use legacy resources */
239 i = 4;
240 }
241
242 /* Set all the bits on, which will allow us to recover the limit data */
243 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) BarArray[i] = 0xFFFFFFFF;
244
245 /* Do the same for the PCI ROM BAR */
246 PciData->u.type0.ROMBaseAddress = PCI_ADDRESS_ROM_ADDRESS_MASK;
247}
248
249VOID
250NTAPI
252{
254 /* Nothing to do for devices */
255 return;
256}
257
258VOID
259NTAPI
261 IN PPCI_COMMON_HEADER PciData,
262 IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
263{
265 UNREFERENCED_PARAMETER(PciData);
266 UNREFERENCED_PARAMETER(IoDescriptor);
267 /* Not yet implemented */
269}
270
271VOID
272NTAPI
274 IN PPCI_COMMON_HEADER PciData)
275{
277 UNREFERENCED_PARAMETER(PciData);
278 /* Not yet implemented */
280}
281
282VOID
283NTAPI
285 IN PPCI_COMMON_HEADER PciData)
286{
289 PULONG BarArray;
290 ULONG Bar, BarMask, i;
291
292 Resources = PdoExtension->Resources;
293 if (!Resources)
294 return;
295
296 /* Write each BAR back with the address that was arbitrated for it */
297 BarArray = PciData->u.type0.BaseAddresses;
298 for (i = 0; i <= PCI_TYPE0_ADDRESSES; i++)
299 {
300 CmDescriptor = &Resources->Current[i];
301
303 {
304 /* A BAR the function does not implement reads back as zero */
305 Bar = BarArray[i];
306 if (!(Bar & ~PCI_ADDRESS_IO_SPACE)) continue;
307
308 /* Work out which bits of this BAR are the address */
310 {
312 }
313 else
314 {
316
317 /* A legacy BAR only decodes the low 20 bits of the address */
319 {
320 BarMask = 0xFFFF0;
321 }
322 }
323
324 BarArray[i] = (Bar & ~BarMask) |
325 (CmDescriptor->u.Memory.Start.LowPart & BarMask);
326
327 /* A 64-bit BAR keeps the high half of its address in the next one */
328 if (!(Bar & PCI_ADDRESS_IO_SPACE) &&
330 {
332 BarArray[i + 1] = CmDescriptor->u.Memory.Start.HighPart;
333 i++;
334 }
335 }
336 else
337 {
338 /* The ROM BAR decodes only while its enable bit is set */
339 Bar = PciData->u.type0.ROMBaseAddress;
340 if (CmDescriptor->Type == CmResourceTypeNull)
341 {
342 PciData->u.type0.ROMBaseAddress = Bar & ~PCI_ROMADDRESS_ENABLED;
343 }
344 else
345 {
346 PciData->u.type0.ROMBaseAddress =
347 (Bar & ~PCI_ADDRESS_ROM_ADDRESS_MASK) |
348 (CmDescriptor->u.Memory.Start.LowPart &
351 }
352 }
353 }
354}
355
356/* EOF */
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
VOID NTAPI Device_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context, IN PPCI_COMMON_HEADER PciData, IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
Definition: device.c:260
VOID NTAPI Device_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension, IN PPCI_COMMON_HEADER PciData)
Definition: device.c:284
VOID NTAPI Device_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
Definition: device.c:119
VOID NTAPI Device_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context)
Definition: device.c:219
VOID NTAPI Device_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
Definition: device.c:20
VOID NTAPI Device_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension, IN PPCI_COMMON_HEADER PciData)
Definition: device.c:273
VOID NTAPI Device_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context)
Definition: device.c:251
BOOLEAN NTAPI PciCreateIoDescriptorFromBarLimit(_Out_ PIO_RESOURCE_DESCRIPTOR ResourceDescriptor, _In_ ULONG Bar, _In_ ULONG NextBar, _In_ BOOLEAN Rom)
Builds the requirement of a BAR from the value it reads back after all ones were written to it.
Definition: utils.c:1179
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
@ PdoExtension
Definition: precomp.h:49
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 const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
void Bar(void)
Definition: terminate.cpp:70
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define CmResourceTypeNull
Definition: restypes.h:103
#define CmResourceTypeMemory
Definition: restypes.h:106
#define CmResourceTypePort
Definition: restypes.h:104
_In_ PVOID Context
Definition: storport.h:2269
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@486::@487 Generic
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@486 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@486::@491 Memory
struct _IO_RESOURCE_DESCRIPTOR::@2481::@2486 Generic
union _IO_RESOURCE_DESCRIPTOR::@2481 u
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define CmResourceTypeMemoryLarge
Definition: cmtypes.h:231
#define PCI_TYPE_64BIT
Definition: iotypes.h:4242
#define PCI_ADDRESS_IO_ADDRESS_MASK
Definition: iotypes.h:4236
#define PCI_TYPE0_ADDRESSES
Definition: iotypes.h:3502
#define PCI_CLASS_MASS_STORAGE_CTLR
Definition: iotypes.h:4106
#define PCI_ADDRESS_IO_SPACE
Definition: iotypes.h:4233
#define PCI_SUBCLASS_MSC_IDE_CTLR
Definition: iotypes.h:4131
#define PCI_TYPE_20BIT
Definition: iotypes.h:4241
#define PCI_ADDRESS_ROM_ADDRESS_MASK
Definition: iotypes.h:4238
#define PCI_ADDRESS_MEMORY_ADDRESS_MASK
Definition: iotypes.h:4237
#define PCI_ROMADDRESS_ENABLED
Definition: iotypes.h:4244
#define PCI_ADDRESS_MEMORY_TYPE_MASK
Definition: iotypes.h:4234
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304