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.

395 lines
10 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. interface.c
  5. Abstract:
  6. IRP_MN_QUERY_INTERFACE lives here.
  7. Author:
  8. Peter Johnston (peterj) 31-Mar-1997
  9. Revision History:
  10. --*/
  11. #include "pcip.h"
  12. NTSTATUS
  13. PciGetBusStandardInterface(
  14. IN PDEVICE_OBJECT Pdo,
  15. OUT PBUS_INTERFACE_STANDARD BusInterface
  16. );
  17. extern PCI_INTERFACE ArbiterInterfaceBusNumber;
  18. extern PCI_INTERFACE ArbiterInterfaceMemory;
  19. extern PCI_INTERFACE ArbiterInterfaceIo;
  20. extern PCI_INTERFACE TranslatorInterfaceInterrupt;
  21. extern PCI_INTERFACE TranslatorInterfaceMemory;
  22. extern PCI_INTERFACE TranslatorInterfaceIo;
  23. extern PCI_INTERFACE BusHandlerInterface;
  24. extern PCI_INTERFACE PciRoutingInterface;
  25. extern PCI_INTERFACE PciCardbusPrivateInterface;
  26. extern PCI_INTERFACE PciLegacyDeviceDetectionInterface;
  27. extern PCI_INTERFACE PciPmeInterface;
  28. extern PCI_INTERFACE PciDevicePresentInterface;
  29. extern PCI_INTERFACE PciNativeIdeInterface;
  30. PPCI_INTERFACE PciInterfaces[] = {
  31. &ArbiterInterfaceBusNumber,
  32. &ArbiterInterfaceMemory,
  33. &ArbiterInterfaceIo,
  34. &BusHandlerInterface,
  35. &PciRoutingInterface,
  36. &PciCardbusPrivateInterface,
  37. &PciLegacyDeviceDetectionInterface,
  38. &PciPmeInterface,
  39. &PciDevicePresentInterface,
  40. &PciNativeIdeInterface,
  41. NULL
  42. };
  43. //
  44. // These are the interfaces we supply only if nobody underneath
  45. // us (the HAL) does.
  46. //
  47. PPCI_INTERFACE PciInterfacesLastResort[] = {
  48. &TranslatorInterfaceInterrupt,
  49. NULL
  50. };
  51. #ifdef ALLOC_PRAGMA
  52. #pragma alloc_text(PAGE, PciQueryInterface)
  53. #pragma alloc_text(PAGE, PciGetBusStandardInterface)
  54. #endif
  55. NTSTATUS
  56. PciGetBusStandardInterface(
  57. IN PDEVICE_OBJECT Pdo,
  58. OUT PBUS_INTERFACE_STANDARD BusInterface
  59. )
  60. /*++
  61. Routine Description:
  62. This routine gets the bus iterface standard information from the PDO.
  63. Arguments:
  64. Pdo - Physical device object to query for this information.
  65. BusInterface - Supplies a pointer for the retrived information.
  66. Return Value:
  67. NT status.
  68. --*/
  69. {
  70. KEVENT event;
  71. NTSTATUS status;
  72. PIRP irp;
  73. IO_STATUS_BLOCK ioStatusBlock;
  74. PIO_STACK_LOCATION irpStack;
  75. PciDebugPrint(
  76. PciDbgObnoxious,
  77. "PCI - PciGetBusStandardInterface entered.\n"
  78. );
  79. KeInitializeEvent( &event, NotificationEvent, FALSE );
  80. irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
  81. Pdo,
  82. NULL,
  83. 0,
  84. NULL,
  85. &event,
  86. &ioStatusBlock );
  87. if (irp == NULL) {
  88. return STATUS_INSUFFICIENT_RESOURCES;
  89. }
  90. irpStack = IoGetNextIrpStackLocation( irp );
  91. irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  92. irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
  93. irpStack->Parameters.QueryInterface.Size = sizeof( BUS_INTERFACE_STANDARD );
  94. irpStack->Parameters.QueryInterface.Version = 1;
  95. irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;
  96. irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  97. //
  98. // Initialize the status to error in case the ACPI driver decides not to
  99. // set it correctly.
  100. //
  101. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  102. status = IoCallDriver( Pdo, irp );
  103. if (!NT_SUCCESS( status)) {
  104. PciDebugPrint(
  105. PciDbgVerbose,
  106. "PCI - PciGetBusStandardInterface IoCallDriver returned %08x.\n",
  107. status
  108. );
  109. return status;
  110. }
  111. if (status == STATUS_PENDING) {
  112. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  113. }
  114. PciDebugPrint(
  115. PciDbgVerbose,
  116. "PCI - PciGetBusStandardInterface returning status %08x.\n",
  117. ioStatusBlock.Status
  118. );
  119. return ioStatusBlock.Status;
  120. }
  121. NTSTATUS
  122. PciQueryInterface(
  123. IN PVOID DeviceExtension,
  124. IN PGUID InterfaceType,
  125. IN USHORT Size,
  126. IN USHORT Version,
  127. IN PVOID InterfaceSpecificData,
  128. IN OUT PINTERFACE InterfaceReturn,
  129. IN BOOLEAN LastChance
  130. )
  131. {
  132. PPCI_INTERFACE *interfaceEntry;
  133. PPCI_INTERFACE interface;
  134. PPCI_INTERFACE *interfaceTable;
  135. BOOLEAN isPdo;
  136. ULONG index;
  137. NTSTATUS status;
  138. #if DBG
  139. UNICODE_STRING guidString;
  140. status = RtlStringFromGUID(InterfaceType, &guidString);
  141. if (NT_SUCCESS(status)) {
  142. PciDebugPrint(
  143. PciDbgVerbose,
  144. "PCI - PciQueryInterface TYPE = %wZ\n",
  145. &guidString
  146. );
  147. RtlFreeUnicodeString(&guidString);
  148. PciDebugPrint(
  149. PciDbgObnoxious,
  150. " Size = %d, Version = %d, InterfaceData = %x, LastChance = %s\n",
  151. Size,
  152. Version,
  153. InterfaceSpecificData,
  154. LastChance ? "TRUE" : "FALSE"
  155. );
  156. }
  157. #endif
  158. isPdo = ((PPCI_PDO_EXTENSION)DeviceExtension)->ExtensionType
  159. == PciPdoExtensionType;
  160. //
  161. // Try to locate the requested interface in the PCI driver's set
  162. // of exported interfaces.
  163. //
  164. // Note - we do not allow last chance interfaces (ie mock translators) for
  165. // machines where we assign bus numbers
  166. //
  167. if (LastChance) {
  168. interfaceTable = PciInterfacesLastResort;
  169. } else {
  170. interfaceTable = PciInterfaces;
  171. }
  172. for (interfaceEntry = interfaceTable; *interfaceEntry; interfaceEntry++) {
  173. interface = *interfaceEntry;
  174. #if 0
  175. status = RtlStringFromGUID(interface->InterfaceType, &guidString);
  176. if (NT_SUCCESS(status)) {
  177. PciDebugPrint(
  178. PciDbgVerbose,
  179. "PCI - PciQueryInterface looking at guid = %wZ\n",
  180. &guidString
  181. );
  182. RtlFreeUnicodeString(&guidString);
  183. }
  184. #endif
  185. //
  186. // Check if this interface is allowed to be used from this
  187. // device object type.
  188. //
  189. if (isPdo) {
  190. if ((interface->Flags & PCIIF_PDO) == 0) {
  191. //
  192. // This interface cannot be used from a PDO.
  193. //
  194. #if DBG
  195. status = RtlStringFromGUID(interface->InterfaceType, &guidString);
  196. if (NT_SUCCESS(status)) {
  197. PciDebugPrint(
  198. PciDbgVerbose,
  199. "PCI - PciQueryInterface: guid = %wZ only for PDOs\n",
  200. &guidString
  201. );
  202. RtlFreeUnicodeString(&guidString);
  203. }
  204. #endif
  205. continue;
  206. }
  207. } else {
  208. //
  209. // Allowable from FDO?
  210. //
  211. if ((interface->Flags & PCIIF_FDO) == 0) {
  212. //
  213. // No.
  214. //
  215. #if DBG
  216. status = RtlStringFromGUID(interface->InterfaceType, &guidString);
  217. if (NT_SUCCESS(status)) {
  218. PciDebugPrint(
  219. PciDbgVerbose,
  220. "PCI - PciQueryInterface: guid = %wZ only for FDOs\n",
  221. &guidString
  222. );
  223. RtlFreeUnicodeString(&guidString);
  224. }
  225. #endif
  226. continue;
  227. }
  228. //
  229. // Allowable only at root?
  230. //
  231. if (interface->Flags & PCIIF_ROOT) {
  232. PPCI_FDO_EXTENSION FdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
  233. if (!PCI_IS_ROOT_FDO(FdoExtension)) {
  234. #if DBG
  235. status = RtlStringFromGUID(interface->InterfaceType, &guidString);
  236. if (NT_SUCCESS(status)) {
  237. PciDebugPrint(
  238. PciDbgVerbose,
  239. "PCI - PciQueryInterface: guid = %wZ only for ROOT\n",
  240. &guidString
  241. );
  242. RtlFreeUnicodeString(&guidString);
  243. }
  244. #endif
  245. continue;
  246. }
  247. }
  248. }
  249. #if DBG
  250. status = RtlStringFromGUID(interface->InterfaceType, &guidString);
  251. if (NT_SUCCESS(status)) {
  252. PciDebugPrint(
  253. PciDbgVerbose,
  254. "PCI - PciQueryInterface looking at guid = %wZ\n",
  255. &guidString
  256. );
  257. RtlFreeUnicodeString(&guidString);
  258. }
  259. #endif
  260. //
  261. // Check for the appropriate GUID then verify version numbers
  262. // and size.
  263. //
  264. if ((PciCompareGuid(InterfaceType, interface->InterfaceType)) &&
  265. (Version >= interface->MinVersion) &&
  266. (Version <= interface->MaxVersion) &&
  267. (Size >= interface->MinSize) ) {
  268. //
  269. // We have a possible hit. Check to see if the interface
  270. // itself agrees.
  271. //
  272. status = interface->Constructor(
  273. DeviceExtension,
  274. interface,
  275. InterfaceSpecificData,
  276. Version,
  277. Size,
  278. InterfaceReturn
  279. );
  280. if (NT_SUCCESS(status)) {
  281. //
  282. // We found and allocated an interface, reference it
  283. // and get out of the loop.
  284. //
  285. InterfaceReturn->InterfaceReference(InterfaceReturn->Context);
  286. PciDebugPrint(
  287. PciDbgObnoxious,
  288. "PCI - PciQueryInterface returning SUCCESS\n"
  289. );
  290. return status;
  291. #if DBG
  292. } else {
  293. PciDebugPrint(
  294. PciDbgVerbose,
  295. "PCI - PciQueryInterface - Contructor %08lx = %08lx\n",
  296. interface->Constructor,
  297. status
  298. );
  299. #endif
  300. }
  301. }
  302. }
  303. //
  304. // Failed to find the requested interface.
  305. //
  306. PciDebugPrint(
  307. PciDbgObnoxious,
  308. "PCI - PciQueryInterface FAILED TO FIND INTERFACE\n"
  309. );
  310. return STATUS_NOT_SUPPORTED;
  311. }