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.

379 lines
9.4 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. pcienum.c
  5. Abstract:
  6. Enumerates the PCI bus and puts all the found PCI information
  7. into the registery.
  8. This is done for debugging & support reasons.
  9. Author:
  10. Ken Reneris
  11. Environment:
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "stdarg.h"
  16. #include "stdio.h"
  17. #include "ntddk.h"
  18. WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
  19. WCHAR rgzConfigurationData[] = L"Configuration Data";
  20. WCHAR rgzIdentifier[] = L"Identifier";
  21. WCHAR rgzPCIIndetifier[] = L"PCI";
  22. WCHAR rgzPCIDump[] = L"PCI configuration space dump";
  23. WCHAR rgzPCIConfigData[] = L"PCIConfigSpaceData";
  24. NTSTATUS
  25. DriverEntry(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PUNICODE_STRING RegistryPath
  28. );
  29. BOOLEAN
  30. FindRegisterLocation (
  31. PHANDLE RegHandle
  32. )
  33. {
  34. UNICODE_STRING unicodeString, ConfigName, IdentName;
  35. OBJECT_ATTRIBUTES objectAttributes;
  36. HANDLE hMFunc, hBus;
  37. NTSTATUS status;
  38. ULONG i, junk, disposition;
  39. WCHAR wstr[8];
  40. PKEY_VALUE_FULL_INFORMATION ValueInfo;
  41. UCHAR buffer [200];
  42. PWSTR p;
  43. //
  44. // Search the hardware description looking for any reported
  45. // PCI bus. The first ARC entry for a PCI bus will contain
  46. // the PCI_REGISTRY_INFO.
  47. //
  48. RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
  49. InitializeObjectAttributes (
  50. &objectAttributes,
  51. &unicodeString,
  52. OBJ_CASE_INSENSITIVE,
  53. NULL, // handle
  54. NULL);
  55. status = ZwOpenKey (&hMFunc, KEY_READ | KEY_WRITE, &objectAttributes);
  56. if (!NT_SUCCESS(status)) {
  57. return FALSE;
  58. }
  59. unicodeString.Buffer = wstr;
  60. unicodeString.MaximumLength = sizeof (wstr);
  61. RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
  62. RtlInitUnicodeString (&IdentName, rgzIdentifier);
  63. ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
  64. for (i=0; TRUE; i++) {
  65. RtlIntegerToUnicodeString (i, 10, &unicodeString);
  66. InitializeObjectAttributes (
  67. &objectAttributes,
  68. &unicodeString,
  69. OBJ_CASE_INSENSITIVE,
  70. hMFunc,
  71. NULL);
  72. status = ZwOpenKey (&hBus, KEY_READ | KEY_WRITE, &objectAttributes);
  73. if (!NT_SUCCESS(status)) {
  74. //
  75. // Out of Multifunction adapter entries...
  76. //
  77. ZwClose (hMFunc);
  78. return FALSE;
  79. }
  80. //
  81. // Check the Indentifier to see if this is a PCI entry
  82. //
  83. status = ZwQueryValueKey (
  84. hBus,
  85. &IdentName,
  86. KeyValueFullInformation,
  87. ValueInfo,
  88. sizeof (buffer),
  89. &junk
  90. );
  91. if (!NT_SUCCESS (status)) {
  92. ZwClose (hBus);
  93. continue;
  94. }
  95. p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
  96. if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
  97. ZwClose (hBus);
  98. continue;
  99. }
  100. // found it...
  101. break;
  102. }
  103. //
  104. // Initialize the object for the key.
  105. //
  106. RtlInitUnicodeString (&unicodeString, rgzPCIDump);
  107. InitializeObjectAttributes(
  108. &objectAttributes,
  109. &unicodeString,
  110. OBJ_CASE_INSENSITIVE,
  111. hBus,
  112. (PSECURITY_DESCRIPTOR) NULL
  113. );
  114. status = ZwCreateKey (
  115. RegHandle,
  116. KEY_READ | KEY_WRITE,
  117. &objectAttributes,
  118. 0,
  119. NULL,
  120. REG_OPTION_VOLATILE,
  121. &disposition
  122. );
  123. return NT_SUCCESS(status);
  124. }
  125. VOID
  126. DumpPciConfigSpaceIntoRegistry (
  127. HANDLE RegHandle
  128. )
  129. {
  130. PCI_SLOT_NUMBER SlotNumber;
  131. ULONG BusNo, DeviceNo, FunctionNo, BytesRead;
  132. BOOLEAN ScanFlag;
  133. PCI_COMMON_CONFIG PciData;
  134. HANDLE HBus, HDevice;
  135. UNICODE_STRING unicodeString;
  136. OBJECT_ATTRIBUTES objectAttributes;
  137. NTSTATUS status;
  138. ULONG len, disposition;
  139. WCHAR wstr[80];
  140. SlotNumber.u.bits.Reserved = 0;
  141. BusNo = 0;
  142. ScanFlag = TRUE;
  143. while (ScanFlag) {
  144. for (DeviceNo=0; ScanFlag && DeviceNo < PCI_MAX_DEVICES; DeviceNo++) {
  145. SlotNumber.u.bits.DeviceNumber = DeviceNo;
  146. for (FunctionNo = 0; FunctionNo < PCI_MAX_FUNCTION; FunctionNo++) {
  147. SlotNumber.u.bits.FunctionNumber = FunctionNo;
  148. BytesRead = HalGetBusData (
  149. PCIConfiguration,
  150. BusNo,
  151. SlotNumber.u.AsULONG,
  152. &PciData,
  153. PCI_COMMON_HDR_LENGTH
  154. );
  155. //
  156. // If end-of-scan
  157. //
  158. if (BytesRead == 0) {
  159. ScanFlag = FALSE;
  160. break;
  161. }
  162. //
  163. // If not present, next device
  164. //
  165. if (PciData.VendorID == PCI_INVALID_VENDORID) {
  166. break;
  167. }
  168. //
  169. // If Intel Device ID, then read complete state
  170. //
  171. if (PciData.VendorID == 0x8086) {
  172. if (PciData.DeviceID == 0x04A3 ||
  173. PciData.DeviceID == 0x0482 ||
  174. PciData.DeviceID == 0x0484) {
  175. BytesRead = HalGetBusData (
  176. PCIConfiguration,
  177. BusNo,
  178. SlotNumber.u.AsULONG,
  179. &PciData,
  180. sizeof (PciData)
  181. );
  182. }
  183. }
  184. //
  185. // Open/Create bus entry in registry
  186. //
  187. swprintf (wstr, L"PCI bus%d", BusNo);
  188. RtlInitUnicodeString (&unicodeString, wstr);
  189. InitializeObjectAttributes(
  190. &objectAttributes,
  191. &unicodeString,
  192. OBJ_CASE_INSENSITIVE,
  193. RegHandle,
  194. (PSECURITY_DESCRIPTOR) NULL
  195. );
  196. status = ZwCreateKey (
  197. &HBus,
  198. KEY_READ | KEY_WRITE,
  199. &objectAttributes,
  200. 0,
  201. NULL,
  202. REG_OPTION_VOLATILE,
  203. &disposition
  204. );
  205. if (!NT_SUCCESS(status)) {
  206. continue;
  207. }
  208. //
  209. // Open/Create device function key
  210. //
  211. swprintf (wstr, L"Device %02d Function %d", DeviceNo, FunctionNo);
  212. RtlInitUnicodeString (&unicodeString, wstr);
  213. InitializeObjectAttributes(
  214. &objectAttributes,
  215. &unicodeString,
  216. OBJ_CASE_INSENSITIVE,
  217. HBus,
  218. (PSECURITY_DESCRIPTOR) NULL
  219. );
  220. status = ZwCreateKey (
  221. &HDevice,
  222. KEY_READ | KEY_WRITE,
  223. &objectAttributes,
  224. 0,
  225. NULL,
  226. REG_OPTION_VOLATILE,
  227. &disposition
  228. );
  229. ZwClose (HBus);
  230. if (!NT_SUCCESS(status)) {
  231. continue;
  232. }
  233. //
  234. // Write PCI config information to registry
  235. //
  236. len = swprintf (wstr, L"%04x-%04x rev %x",
  237. PciData.VendorID,
  238. PciData.DeviceID,
  239. PciData.RevisionID
  240. );
  241. RtlInitUnicodeString (&unicodeString, L"Device ID");
  242. ZwSetValueKey (
  243. HDevice,
  244. &unicodeString,
  245. 0L,
  246. REG_SZ,
  247. wstr,
  248. sizeof (WCHAR) * len
  249. );
  250. RtlInitUnicodeString (&unicodeString, L"RawData");
  251. ZwSetValueKey (
  252. HDevice,
  253. &unicodeString,
  254. 0L,
  255. REG_BINARY,
  256. &PciData,
  257. BytesRead
  258. );
  259. ZwClose (HDevice);
  260. }
  261. }
  262. BusNo += 1;
  263. }
  264. }
  265. NTSTATUS
  266. DriverEntry(
  267. IN PDRIVER_OBJECT DriverObject,
  268. IN PUNICODE_STRING RegistryPath
  269. )
  270. /*++
  271. Routine Description:
  272. Arguments:
  273. DriverObject - Pointer to driver object created by system.
  274. RegistryPath - Pointer to the Unicode name of the registry path
  275. for this driver.
  276. Return Value:
  277. The function value is the final status from the initialization operation.
  278. --*/
  279. {
  280. BOOLEAN flag;
  281. HANDLE RegHandle;
  282. flag = FindRegisterLocation (&RegHandle);
  283. if (flag) {
  284. DumpPciConfigSpaceIntoRegistry (RegHandle);
  285. ZwClose (RegHandle);
  286. }
  287. // never load
  288. return STATUS_UNSUCCESSFUL;
  289. }