Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

492 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. arb_comn.c
  5. Abstract:
  6. This module contains arbitration generic "utility" routines
  7. for the PCI driver.
  8. Author:
  9. Peter Johnston (peterj) 1-Apr-1997
  10. Andrew Thornton (andrewth) 15-May-1997
  11. Revision History:
  12. --*/
  13. #include "pcip.h"
  14. #define PCI_CONTEXT_TO_INSTANCE(context) \
  15. CONTAINING_RECORD(context, PCI_ARBITER_INSTANCE, CommonInstance)
  16. //
  17. // Plain text (short) description of each arbiter type.
  18. // (For debug).
  19. //
  20. // N.B. Order corresponds to PCI Signature enumeration.
  21. //
  22. PUCHAR PciArbiterNames[] = {
  23. "I/O Port",
  24. "Memory",
  25. "Interrupt",
  26. "Bus Number"
  27. };
  28. VOID
  29. PciArbiterDestructor(
  30. IN PVOID Extension
  31. )
  32. /*++
  33. Routine Description:
  34. This routine is called when a PCI Secondary Extension that
  35. contains an arbiter instance is being torn down. Its function
  36. is to do any arbiter specific teardown.
  37. Arguments:
  38. Extension Address of PCI secondary extension containing
  39. the arbiter.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. PPCI_ARBITER_INSTANCE instance;
  45. PARBITER_INSTANCE arbiter;
  46. PARBITER_MEMORY_EXTENSION extension;
  47. instance = (PPCI_ARBITER_INSTANCE)Extension;
  48. arbiter = &instance->CommonInstance;
  49. ASSERT(!arbiter->ReferenceCount);
  50. ASSERT(!arbiter->TransactionInProgress);
  51. //
  52. // NTRAID #54671 - 04/03/2000 - andrewth
  53. // This is rather gross but it fixes the leak from the memory
  54. // arbiter.
  55. //
  56. if (arbiter->ResourceType == CmResourceTypeMemory) {
  57. extension = arbiter->Extension;
  58. ASSERT(extension);
  59. ArbFreeOrderingList(&extension->PrefetchableOrdering);
  60. ArbFreeOrderingList(&extension->NonprefetchableOrdering);
  61. ArbFreeOrderingList(&extension->OriginalOrdering);
  62. //
  63. // Arbiter->OrderingList is one of the above three lists we just freed -
  64. // don't free it again
  65. //
  66. RtlZeroMemory(&arbiter->OrderingList, sizeof(ARBITER_ORDERING_LIST));
  67. }
  68. ArbDeleteArbiterInstance(arbiter);
  69. }
  70. NTSTATUS
  71. PciArbiterInitializeInterface(
  72. IN PVOID DeviceExtension,
  73. IN PCI_SIGNATURE DesiredInterface,
  74. IN OUT PARBITER_INTERFACE ArbiterInterface
  75. )
  76. {
  77. PPCI_ARBITER_INSTANCE instance;
  78. PPCI_FDO_EXTENSION fdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
  79. //
  80. // Find the arbiter instance (context) for this resource type
  81. // on this FDO.
  82. //
  83. instance = PciFindSecondaryExtension(fdoExtension, DesiredInterface);
  84. if (instance == NULL) {
  85. #if DBG
  86. //
  87. // Check if this bridge is doing subtractive decoding in
  88. // which case there will be no arbiter for IO or Memory.
  89. //
  90. // N.B. Only relevant to debug, either way the call will
  91. // fail but we don't want to actually assert if this is
  92. // the case.
  93. //
  94. if (!PCI_IS_ROOT_FDO(fdoExtension)) {
  95. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)
  96. fdoExtension->PhysicalDeviceObject->DeviceExtension;
  97. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  98. if (pdoExtension->Dependent.type1.SubtractiveDecode) {
  99. //
  100. // Subtractive, no arbiters.
  101. //
  102. return STATUS_INVALID_PARAMETER_2;
  103. }
  104. }
  105. ASSERTMSG("couldn't locate arbiter for resource.", instance);
  106. #endif
  107. return STATUS_INVALID_PARAMETER_5;
  108. }
  109. //
  110. // Fill in the rest of the caller's arbiter interface structure.
  111. //
  112. ArbiterInterface->Context = &instance->CommonInstance;
  113. PciDebugPrint(
  114. PciDbgObnoxious,
  115. "PCI - %S Arbiter Interface Initialized.\n",
  116. instance->CommonInstance.Name
  117. );
  118. return STATUS_SUCCESS;
  119. }
  120. NTSTATUS
  121. PciInitializeArbiters(
  122. IN PVOID DeviceExtension
  123. )
  124. {
  125. NTSTATUS status;
  126. PPCI_INTERFACE *interfaceEntry;
  127. PCI_SIGNATURE arbiterType;
  128. PPCI_ARBITER_INSTANCE instance;
  129. PPCI_FDO_EXTENSION fdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
  130. PRTL_RANGE_LIST *range;
  131. ULONG i;
  132. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  133. //
  134. // For each resource type for which we do arbitration, initialize
  135. // a context.
  136. //
  137. for (arbiterType = PciArb_Io;
  138. arbiterType <= PciArb_BusNumber;
  139. arbiterType++) {
  140. //
  141. // If this bridge provides this resource via subtractive
  142. // decode, get the system to fall thru to the parent
  143. // arbiter by not creating an arbiter at this level.
  144. //
  145. if (!PCI_IS_ROOT_FDO(fdoExtension)) {
  146. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)
  147. fdoExtension->PhysicalDeviceObject->DeviceExtension;
  148. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  149. if (pdoExtension->Dependent.type1.SubtractiveDecode) {
  150. //
  151. // Skip creation of this arbiter.
  152. //
  153. PciDebugPrint(
  154. PciDbgVerbose,
  155. "PCI Not creating arbiters for subtractive bus %d\n",
  156. pdoExtension->Dependent.type1.SecondaryBus
  157. );
  158. continue;
  159. }
  160. }
  161. //
  162. // Find this entry in the interface table (if not found, skip
  163. // it).
  164. //
  165. for (interfaceEntry = PciInterfaces;
  166. *interfaceEntry;
  167. interfaceEntry++) {
  168. if ((*interfaceEntry)->Signature == arbiterType) {
  169. break;
  170. }
  171. }
  172. if (*interfaceEntry == NULL) {
  173. //
  174. // Did not find an interface entry. This means we don't
  175. // actually implement this arbiter type.
  176. //
  177. PciDebugPrint(
  178. PciDbgObnoxious,
  179. "PCI - FDO ext 0x%08x no %s arbiter.\n",
  180. DeviceExtension,
  181. PciArbiterNames[arbiterType - PciArb_Io]
  182. );
  183. continue;
  184. }
  185. instance = ExAllocatePool(
  186. PagedPool | POOL_COLD_ALLOCATION,
  187. sizeof(PCI_ARBITER_INSTANCE)
  188. );
  189. if (instance == NULL) {
  190. return STATUS_INSUFFICIENT_RESOURCES;
  191. }
  192. //
  193. // Initialize PCI specific fields
  194. //
  195. instance->BusFdoExtension = fdoExtension;
  196. instance->Interface = *interfaceEntry;
  197. swprintf(
  198. instance->InstanceName,
  199. L"PCI %S (b=%02x)",
  200. PciArbiterNames[arbiterType - PciArb_Io],
  201. fdoExtension->BaseBus
  202. );
  203. //
  204. // Allow this arbiter to do any of it's own first time
  205. // initialization.
  206. //
  207. status = (*interfaceEntry)->Initializer(instance);
  208. if (!NT_SUCCESS(status)) {
  209. return status;
  210. }
  211. //
  212. // Push this arbiter onto the FDO's list of extensions.
  213. //
  214. PciLinkSecondaryExtension(fdoExtension,
  215. instance,
  216. arbiterType,
  217. PciArbiterDestructor);
  218. PciDebugPrint(
  219. PciDbgObnoxious,
  220. "PCI - FDO ext 0x%08x %S arbiter initialized (context 0x%08x).\n",
  221. DeviceExtension,
  222. instance->CommonInstance.Name,
  223. instance
  224. );
  225. }
  226. return STATUS_SUCCESS;
  227. }
  228. NTSTATUS
  229. PciInitializeArbiterRanges(
  230. IN PPCI_FDO_EXTENSION FdoExtension,
  231. IN PCM_RESOURCE_LIST ResourceList
  232. )
  233. {
  234. NTSTATUS status;
  235. PCI_SIGNATURE arbiterType;
  236. CM_RESOURCE_TYPE resourceType;
  237. PPCI_ARBITER_INSTANCE instance;
  238. //
  239. // NTRAID #95564 - 04/03/2000 - andrewth
  240. // This routine needs to be reworked, in the case where
  241. // this FDO is processing a second or subsequent START_DEVICE
  242. // IRP, the arbiter's ranges may need to be adjusted according
  243. // to the incoming resource list. Until this is done, avoid
  244. // causing problems by processing it again.
  245. //
  246. if (FdoExtension->ArbitersInitialized) {
  247. PciDebugPrint(
  248. PciDbgInformative,
  249. "PCI Warning hot start FDOx %08x, resource ranges not checked.\n",
  250. FdoExtension
  251. );
  252. return STATUS_INVALID_DEVICE_REQUEST;
  253. }
  254. //
  255. // Check if this bridge is doing subtractive decoding in
  256. // which case there will be no arbiters
  257. //
  258. if (!PCI_IS_ROOT_FDO(FdoExtension)) {
  259. PPCI_PDO_EXTENSION pdoExtension;
  260. pdoExtension = (PPCI_PDO_EXTENSION)
  261. FdoExtension->PhysicalDeviceObject->DeviceExtension;
  262. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  263. if (pdoExtension->Dependent.type1.SubtractiveDecode) {
  264. //
  265. // Subtractive decode no arbiters.
  266. //
  267. PciDebugPrint(
  268. PciDbgInformative,
  269. "PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n",
  270. FdoExtension
  271. );
  272. return STATUS_SUCCESS;
  273. }
  274. }
  275. //
  276. // For each resource type for which we do arbitration, initialize
  277. // a context.
  278. //
  279. for (arbiterType = PciArb_Io;
  280. arbiterType <= PciArb_Memory;
  281. arbiterType++) {
  282. //
  283. // Currently this is only supported for Memory and IO.
  284. //
  285. switch (arbiterType) {
  286. //
  287. // Go ahead and process these ones.
  288. //
  289. case PciArb_Io:
  290. resourceType = CmResourceTypePort;
  291. break;
  292. case PciArb_Memory:
  293. resourceType = CmResourceTypeMemory;
  294. break;
  295. default:
  296. //
  297. // Skip anything else.
  298. //
  299. continue;
  300. }
  301. //
  302. // Find this arbiter instance.
  303. //
  304. instance = PciFindSecondaryExtension(FdoExtension, arbiterType);
  305. if (instance == NULL) {
  306. //
  307. // Did not find an interface entry. This means we don't
  308. // actually implement this arbiter type.
  309. //
  310. PciDebugPrint(
  311. PciDbgAlways,
  312. "PCI - FDO ext 0x%08x %s arbiter (REQUIRED) is missing.\n",
  313. FdoExtension,
  314. PciArbiterNames[arbiterType - PciArb_Io]
  315. );
  316. continue;
  317. }
  318. //
  319. // The incoming ResourceList gives the ranges this bus supports.
  320. // Convert this to an inverted range so we can exclude everything
  321. // we don't cover.
  322. //
  323. status = PciRangeListFromResourceList(
  324. FdoExtension,
  325. ResourceList,
  326. resourceType,
  327. TRUE,
  328. instance->CommonInstance.Allocation
  329. );
  330. if (!NT_SUCCESS(status)) {
  331. //
  332. // Nothing we can do here. Additional debug stuff was
  333. // in the lower level. Skip this puppy.
  334. //
  335. continue;
  336. }
  337. //
  338. // NTRAID #95564 - 04/03/2000 - andrewth
  339. //
  340. // When ArbStartArbiter is complete it will replace
  341. // the call to PciRangeListFromResourceList.
  342. //
  343. ASSERT(instance->CommonInstance.StartArbiter);
  344. status = instance->CommonInstance.StartArbiter(&instance->CommonInstance,
  345. ResourceList
  346. );
  347. if (!NT_SUCCESS(status)) {
  348. //
  349. // Bail initializing this arbiter and fail the start. The arbiters
  350. // will be cleaned up when we get the REMOVE_DEVICE
  351. //
  352. return status;
  353. }
  354. }
  355. return STATUS_SUCCESS;
  356. }
  357. VOID
  358. PciReferenceArbiter(
  359. IN PVOID Context
  360. )
  361. {
  362. PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context);
  363. InterlockedIncrement(&instance->CommonInstance.ReferenceCount);
  364. }
  365. VOID
  366. PciDereferenceArbiter(
  367. IN PVOID Context
  368. )
  369. {
  370. PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context);
  371. InterlockedDecrement(&instance->CommonInstance.ReferenceCount);
  372. }