Leaked source code of windows server 2003
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.

494 lines
13 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. PCI_ASSERT(!arbiter->ReferenceCount);
  50. PCI_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. PCI_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. PCI_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. BOOLEAN ok;
  131. ASSERT_PCI_FDO_EXTENSION(fdoExtension);
  132. //
  133. // For each resource type for which we do arbitration, initialize
  134. // a context.
  135. //
  136. for (arbiterType = PciArb_Io;
  137. arbiterType <= PciArb_BusNumber;
  138. arbiterType++) {
  139. //
  140. // If this bridge provides this resource via subtractive
  141. // decode, get the system to fall thru to the parent
  142. // arbiter by not creating an arbiter at this level.
  143. //
  144. if (!PCI_IS_ROOT_FDO(fdoExtension)) {
  145. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)
  146. fdoExtension->PhysicalDeviceObject->DeviceExtension;
  147. ASSERT_PCI_PDO_EXTENSION(pdoExtension);
  148. if (pdoExtension->Dependent.type1.SubtractiveDecode) {
  149. //
  150. // Skip creation of this arbiter.
  151. //
  152. PciDebugPrint(
  153. PciDbgVerbose,
  154. "PCI Not creating arbiters for subtractive bus %d\n",
  155. pdoExtension->Dependent.type1.SecondaryBus
  156. );
  157. continue;
  158. }
  159. }
  160. //
  161. // Find this entry in the interface table (if not found, skip
  162. // it).
  163. //
  164. for (interfaceEntry = PciInterfaces;
  165. *interfaceEntry;
  166. interfaceEntry++) {
  167. if ((*interfaceEntry)->Signature == arbiterType) {
  168. break;
  169. }
  170. }
  171. if (*interfaceEntry == NULL) {
  172. //
  173. // Did not find an interface entry. This means we don't
  174. // actually implement this arbiter type.
  175. //
  176. PciDebugPrint(
  177. PciDbgObnoxious,
  178. "PCI - FDO ext 0x%08x no %s arbiter.\n",
  179. DeviceExtension,
  180. PciArbiterNames[arbiterType - PciArb_Io]
  181. );
  182. continue;
  183. }
  184. instance = ExAllocatePool(
  185. PagedPool | POOL_COLD_ALLOCATION,
  186. sizeof(PCI_ARBITER_INSTANCE)
  187. );
  188. if (instance == NULL) {
  189. return STATUS_INSUFFICIENT_RESOURCES;
  190. }
  191. //
  192. // Initialize PCI specific fields
  193. //
  194. instance->BusFdoExtension = fdoExtension;
  195. instance->Interface = *interfaceEntry;
  196. ok = SUCCEEDED(StringCbPrintfW(instance->InstanceName,
  197. sizeof(instance->InstanceName),
  198. L"PCI %S (b=%02x)",
  199. PciArbiterNames[arbiterType - PciArb_Io],
  200. fdoExtension->BaseBus
  201. ));
  202. ASSERT(ok);
  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. PCI_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. FdoExtension->ArbitersInitialized = TRUE;
  356. return STATUS_SUCCESS;
  357. }
  358. VOID
  359. PciReferenceArbiter(
  360. IN PVOID Context
  361. )
  362. {
  363. PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context);
  364. InterlockedIncrement(&instance->CommonInstance.ReferenceCount);
  365. }
  366. VOID
  367. PciDereferenceArbiter(
  368. IN PVOID Context
  369. )
  370. {
  371. PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context);
  372. InterlockedDecrement(&instance->CommonInstance.ReferenceCount);
  373. }