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 *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 /* FUNCTIONS ******************************************************************/
21 Device_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context
)
23 PPCI_COMMON_HEADER PciData
;
24 PIO_RESOURCE_DESCRIPTOR IoDescriptor
;
25 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
;
26 PPCI_FUNCTION_RESOURCES Resources
;
28 ULONG Bar
, BarMask
, i
;
30 /* Get variables from context */
31 PciData
= Context
->Current
;
32 Resources
= Context
->PdoExtension
->Resources
;
34 /* Loop all the PCI BARs */
35 BarArray
= PciData
->u
.type0
.BaseAddresses
;
36 for (i
= 0; i
<= PCI_TYPE0_ADDRESSES
; i
++)
38 /* Get the resource descriptor and limit descriptor for this BAR */
39 CmDescriptor
= &Resources
->Current
[i
];
40 IoDescriptor
= &Resources
->Limit
[i
];
42 /* Build the resource descriptor based on the limit descriptor */
43 CmDescriptor
->Type
= IoDescriptor
->Type
;
44 if (CmDescriptor
->Type
== CmResourceTypeNull
) continue;
45 CmDescriptor
->Flags
= IoDescriptor
->Flags
;
46 CmDescriptor
->ShareDisposition
= IoDescriptor
->ShareDisposition
;
47 CmDescriptor
->u
.Generic
.Start
.HighPart
= 0;
48 CmDescriptor
->u
.Generic
.Length
= IoDescriptor
->u
.Generic
.Length
;
50 /* Read the actual BAR value */
53 /* Check which BAR is being processed now */
54 if (i
!= PCI_TYPE0_ADDRESSES
)
56 /* Check if this is an I/O BAR */
57 if (Bar
& PCI_ADDRESS_IO_SPACE
)
59 /* Use the right mask to get the I/O port base address */
60 ASSERT(CmDescriptor
->Type
== CmResourceTypePort
);
61 BarMask
= PCI_ADDRESS_IO_ADDRESS_MASK
;
65 /* It's a RAM BAR, use the right mask to get the base address */
66 ASSERT(CmDescriptor
->Type
== CmResourceTypeMemory
);
67 BarMask
= PCI_ADDRESS_MEMORY_ADDRESS_MASK
;
69 /* Check if it's a 64-bit BAR */
70 if ((Bar
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
)
72 /* The next BAR value is actually the high 32-bits */
73 CmDescriptor
->u
.Memory
.Start
.HighPart
= BarArray
[i
+ 1];
75 else if ((Bar
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_20BIT
)
77 /* Legacy BAR, don't read more than 20 bits of the address */
84 /* Actually a ROM BAR, so read the correct register */
85 Bar
= PciData
->u
.type0
.ROMBaseAddress
;
87 /* Apply the correct mask for ROM BARs */
88 BarMask
= PCI_ADDRESS_ROM_ADDRESS_MASK
;
90 /* Make sure it's enabled */
91 if (!(Bar
& PCI_ROMADDRESS_ENABLED
))
93 /* If it isn't, then a descriptor won't be built for it */
94 CmDescriptor
->Type
= CmResourceTypeNull
;
99 /* Now we have the right mask, read the actual address from the BAR */
101 CmDescriptor
->u
.Memory
.Start
.LowPart
= Bar
;
103 /* And check for invalid BAR addresses */
104 if (!(CmDescriptor
->u
.Memory
.Start
.HighPart
| Bar
))
106 /* Skip these descriptors */
107 CmDescriptor
->Type
= CmResourceTypeNull
;
108 DPRINT1("Invalid BAR\n");
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
;
119 Device_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context
)
121 PPCI_COMMON_HEADER Current
, PciData
;
122 PPCI_PDO_EXTENSION PdoExtension
;
124 PIO_RESOURCE_DESCRIPTOR Limit
;
127 /* Get pointers from the context */
128 PdoExtension
= Context
->PdoExtension
;
129 Current
= Context
->Current
;
130 PciData
= Context
->PciData
;
132 /* And get the array of bARs */
133 BarArray
= PciData
->u
.type0
.BaseAddresses
;
135 /* First, check for IDE controllers that are not in native mode */
136 if ((PdoExtension
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
137 (PdoExtension
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
) &&
138 (PdoExtension
->ProgIf
& 5) != 5)
140 /* They should not be using any non-legacy resources */
146 else if ((PdoExtension
->VendorId
== 0x5333) &&
147 ((PdoExtension
->DeviceId
== 0x88F0) ||
148 (PdoExtension
->DeviceId
== 0x8880)))
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
157 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
159 /* Find its 32MB RAM BAR */
160 if (BarArray
[i
] == 0xFE000000)
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");
169 /* Check for Cirrus Logic GD5430/5440 cards */
170 if ((PdoExtension
->VendorId
== 0x1013) && (PdoExtension
->DeviceId
== 0xA0))
172 /* Check for the I/O port requirement */
173 if (BarArray
[1] == 0xFC01)
175 /* Check for completely bogus BAR */
176 if (Current
->u
.type0
.BaseAddresses
[1] == 1)
180 DPRINT1("PCI - Ignored Cirrus GD54xx broken IO requirement (400 ports)\n");
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]);
189 else if (BarArray
[1])
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",
197 /* Finally, process all the limit descriptors */
198 Limit
= PdoExtension
->Resources
->Limit
;
199 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
201 /* And build them based on the BARs */
202 if (PciCreateIoDescriptorFromBarLimit(&Limit
[i
], &BarArray
[i
], FALSE
))
204 /* This function returns TRUE if the BAR was 64-bit, handle this */
205 ASSERT((i
+ 1) < PCI_TYPE0_ADDRESSES
);
207 Limit
[i
].Type
= CmResourceTypeNull
;
211 /* Create the last descriptor based on the ROM address */
212 PciCreateIoDescriptorFromBarLimit(&Limit
[i
],
213 &PciData
->u
.type0
.ROMBaseAddress
,
219 Device_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context
)
221 PPCI_COMMON_HEADER PciData
;
222 PPCI_PDO_EXTENSION PdoExtension
;
226 /* Get pointers from context data */
227 PdoExtension
= Context
->PdoExtension
;
228 PciData
= Context
->PciData
;
230 /* Get the array of BARs */
231 BarArray
= PciData
->u
.type0
.BaseAddresses
;
233 /* Check for IDE controllers that are not in native mode */
234 if ((PdoExtension
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
235 (PdoExtension
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
) &&
236 (PdoExtension
->ProgIf
& 5) != 5)
238 /* These controllers only use legacy resources */
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;
245 /* Do the same for the PCI ROM BAR */
246 PciData
->u
.type0
.ROMBaseAddress
= PCI_ADDRESS_ROM_ADDRESS_MASK
;
251 Device_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT 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 /* Not yet implemented */
270 Device_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension
,
271 IN PPCI_COMMON_HEADER PciData
)
273 /* Not yet implemented */
280 Device_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension
,
281 IN PPCI_COMMON_HEADER PciData
)
283 /* Not yet implemented */