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
9 /* INCLUDES *******************************************************************/
16 /* FUNCTIONS ******************************************************************/
20 Device_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context
)
22 PPCI_COMMON_HEADER PciData
;
23 PIO_RESOURCE_DESCRIPTOR IoDescriptor
;
24 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
;
25 PPCI_FUNCTION_RESOURCES Resources
;
27 ULONG Bar
, BarMask
, i
;
29 /* Get variables from context */
30 PciData
= Context
->Current
;
31 Resources
= Context
->PdoExtension
->Resources
;
33 /* Loop all the PCI BARs */
34 BarArray
= PciData
->u
.type0
.BaseAddresses
;
35 for (i
= 0; i
<= PCI_TYPE0_ADDRESSES
; i
++)
37 /* Get the resource descriptor and limit descriptor for this BAR */
38 CmDescriptor
= &Resources
->Current
[i
];
39 IoDescriptor
= &Resources
->Limit
[i
];
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
;
49 /* Check if we're handling PCI BARs, or the ROM BAR */
50 if (i
< PCI_TYPE0_ADDRESSES
)
52 /* Read the actual BAR value */
55 /* Check if this is an I/O BAR */
56 if (Bar
& PCI_ADDRESS_IO_SPACE
)
58 /* Use the right mask to get the I/O port base address */
59 ASSERT(CmDescriptor
->Type
== CmResourceTypePort
);
60 BarMask
= PCI_ADDRESS_IO_ADDRESS_MASK
;
64 /* It's a RAM BAR, use the right mask to get the base address */
65 ASSERT(CmDescriptor
->Type
== CmResourceTypeMemory
);
66 BarMask
= PCI_ADDRESS_MEMORY_ADDRESS_MASK
;
68 /* Check if it's a 64-bit BAR */
69 if ((Bar
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
)
71 /* The next BAR value is actually the high 32-bits */
72 CmDescriptor
->u
.Memory
.Start
.HighPart
= BarArray
[i
+ 1];
74 else if ((Bar
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_20BIT
)
76 /* Legacy BAR, don't read more than 20 bits of the address */
83 /* Actually a ROM BAR, so read the correct register */
84 Bar
= PciData
->u
.type0
.ROMBaseAddress
;
86 /* Apply the correct mask for ROM BARs */
87 BarMask
= PCI_ADDRESS_ROM_ADDRESS_MASK
;
89 /* Make sure it's enabled */
90 if (!(Bar
& PCI_ROMADDRESS_ENABLED
))
92 /* If it isn't, then a descriptor won't be built for it */
93 CmDescriptor
->Type
= CmResourceTypeNull
;
98 /* Now we have the right mask, read the actual address from the BAR */
100 CmDescriptor
->u
.Memory
.Start
.LowPart
= Bar
;
102 /* And check for invalid BAR addresses */
103 if (!(CmDescriptor
->u
.Memory
.Start
.HighPart
| Bar
))
105 /* Skip these descriptors */
106 CmDescriptor
->Type
= CmResourceTypeNull
;
107 DPRINT1("Invalid BAR\n");
111 /* Also save the sub-IDs that came directly from the PCI header */
112 Context
->PdoExtension
->SubsystemVendorId
= PciData
->u
.type0
.SubVendorID
;
113 Context
->PdoExtension
->SubsystemId
= PciData
->u
.type0
.SubSystemID
;
118 Device_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context
)
120 PPCI_COMMON_HEADER Current
, PciData
;
121 PPCI_PDO_EXTENSION PdoExtension
;
123 PIO_RESOURCE_DESCRIPTOR Limit
;
126 /* Get pointers from the context */
127 PdoExtension
= Context
->PdoExtension
;
128 Current
= Context
->Current
;
129 PciData
= Context
->PciData
;
131 /* And get the array of bARs */
132 BarArray
= PciData
->u
.type0
.BaseAddresses
;
134 /* First, check for IDE controllers that are not in native mode */
135 if ((PdoExtension
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
136 (PdoExtension
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
) &&
137 (PdoExtension
->ProgIf
& 5) != 5)
139 /* They should not be using any non-legacy resources */
145 else if ((PdoExtension
->VendorId
== 0x5333) &&
146 ((PdoExtension
->DeviceId
== 0x88F0) ||
147 (PdoExtension
->DeviceId
== 0x8880)))
150 * The problem is caused by the S3 Vision 968/868 video controller which
151 * is used on the Diamond Stealth 64 Video 3000 series, Number Nine 9FX
152 * motion 771, and other popular video cards, all containing a memory bug.
153 * The 968/868 claims to require 32 MB of memory, but it actually decodes
156 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
158 /* Find its 32MB RAM BAR */
159 if (BarArray
[i
] == 0xFE000000)
161 /* Increase it to 64MB to make sure nobody touches the buffer */
162 BarArray
[i
] = 0xFC000000;
163 DPRINT1("PCI - Adjusted broken S3 requirement from 32MB to 64MB\n");
168 /* Check for Cirrus Logic GD5430/5440 cards */
169 if ((PdoExtension
->VendorId
== 0x1013) && (PdoExtension
->DeviceId
== 0xA0))
171 /* Check for the I/O port requirement */
172 if (BarArray
[1] == 0xFC01)
174 /* Check for completely bogus BAR */
175 if (Current
->u
.type0
.BaseAddresses
[1] == 1)
179 DPRINT1("PCI - Ignored Cirrus GD54xx broken IO requirement (400 ports)\n");
183 /* Otherwise, this BAR seems okay */
184 DPRINT1("PCI - Cirrus GD54xx 400 port IO requirement has a valid setting (%08x)\n",
185 Current
->u
.type0
.BaseAddresses
[1]);
188 else if (BarArray
[1])
190 /* Strange, the I/O BAR was not found as expected (or at all) */
191 DPRINT1("PCI - Warning Cirrus Adapter 101300a0 has unexpected resource requirement (%08x)\n",
196 /* Finally, process all the limit descriptors */
197 Limit
= PdoExtension
->Resources
->Limit
;
198 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
200 /* And build them based on the BARs */
201 if (PciCreateIoDescriptorFromBarLimit(&Limit
[i
], &BarArray
[i
], FALSE
))
203 /* This function returns TRUE if the BAR was 64-bit, handle this */
204 ASSERT((i
+ 1) < PCI_TYPE0_ADDRESSES
);
206 Limit
[i
].Type
= CmResourceTypeNull
;
210 /* Create the last descriptor based on the ROM address */
211 PciCreateIoDescriptorFromBarLimit(&Limit
[i
],
212 &PciData
->u
.type0
.ROMBaseAddress
,
218 Device_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context
)
220 PPCI_COMMON_HEADER PciData
;
221 PPCI_PDO_EXTENSION PdoExtension
;
225 /* Get pointers from context data */
226 PdoExtension
= Context
->PdoExtension
;
227 PciData
= Context
->PciData
;
229 /* Get the array of BARs */
230 BarArray
= PciData
->u
.type0
.BaseAddresses
;
232 /* Check for IDE controllers that are not in native mode */
233 if ((PdoExtension
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
234 (PdoExtension
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
) &&
235 (PdoExtension
->ProgIf
& 5) != 5)
237 /* These controllers only use legacy resources */
241 /* Set all the bits on, which will allow us to recover the limit data */
242 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++) BarArray
[i
] = 0xFFFFFFFF;
244 /* Do the same for the PCI ROM BAR */
245 PciData
->u
.type0
.ROMBaseAddress
= PCI_ADDRESS_ROM_ADDRESS_MASK
;
250 Device_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context
)
252 UNREFERENCED_PARAMETER(Context
);
253 /* Nothing to do for devices */
259 Device_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context
,
260 IN PPCI_COMMON_HEADER PciData
,
261 IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
)
263 UNREFERENCED_PARAMETER(Context
);
264 UNREFERENCED_PARAMETER(PciData
);
265 UNREFERENCED_PARAMETER(IoDescriptor
);
266 /* Not yet implemented */
267 UNIMPLEMENTED_DBGBREAK();
272 Device_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension
,
273 IN PPCI_COMMON_HEADER PciData
)
275 UNREFERENCED_PARAMETER(PdoExtension
);
276 UNREFERENCED_PARAMETER(PciData
);
277 /* Not yet implemented */
278 UNIMPLEMENTED_DBGBREAK();
283 Device_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension
,
284 IN PPCI_COMMON_HEADER PciData
)
286 UNREFERENCED_PARAMETER(PdoExtension
);
287 UNREFERENCED_PARAMETER(PciData
);
288 /* Not yet implemented */
289 UNIMPLEMENTED_DBGBREAK();