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.

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