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.

389 lines
12 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. PnpEisa.c
  5. Abstract:
  6. This file implements Eisa related code.
  7. Author:
  8. Shie-Lin Tzong (shielint)
  9. Environment:
  10. Kernel Mode.
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "pnpmgrp.h"
  15. #pragma hdrstop
  16. #ifdef POOL_TAGGING
  17. #undef ExAllocatePool
  18. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'iepP')
  19. #endif
  20. #define EISA_DEVICE_NODE_NAME L"EisaResources"
  21. #define BUFFER_LENGTH 50
  22. NTSTATUS
  23. EisaGetEisaDevicesResources (
  24. OUT PCM_RESOURCE_LIST *ResourceList,
  25. OUT PULONG ResourceLength
  26. );
  27. NTSTATUS
  28. EisaBuildSlotsResources (
  29. IN ULONG SlotMasks,
  30. IN ULONG NumberMasks,
  31. OUT PCM_RESOURCE_LIST *Resource,
  32. OUT ULONG *Length
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(INIT, EisaBuildEisaDeviceNode)
  36. #pragma alloc_text(INIT, EisaGetEisaDevicesResources)
  37. #pragma alloc_text(INIT, EisaBuildSlotsResources)
  38. #endif
  39. NTSTATUS
  40. EisaBuildEisaDeviceNode (
  41. VOID
  42. )
  43. /*++
  44. Routine Description:
  45. This routine build an registry key to report eisa resources to arbiters.
  46. Arguments:
  47. None.
  48. Return Value:
  49. NTSTATUS code.
  50. --*/
  51. {
  52. NTSTATUS status;
  53. ULONG disposition, tmpValue;
  54. WCHAR buffer[BUFFER_LENGTH];
  55. UNICODE_STRING unicodeString;
  56. HANDLE rootHandle, deviceHandle, instanceHandle, logConfHandle;
  57. PCM_RESOURCE_LIST resourceList;
  58. ULONG resourceLength;
  59. status = EisaGetEisaDevicesResources(&resourceList, &resourceLength);
  60. if (!NT_SUCCESS(status) || resourceList == NULL) {
  61. return STATUS_UNSUCCESSFUL;
  62. }
  63. PiWstrToUnicodeString(&unicodeString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root");
  64. status = IopOpenRegistryKeyEx( &rootHandle,
  65. NULL,
  66. &unicodeString,
  67. KEY_ALL_ACCESS
  68. );
  69. if (!NT_SUCCESS(status)) {
  70. if (resourceList) {
  71. ExFreePool (resourceList);
  72. }
  73. return status;
  74. }
  75. PiWstrToUnicodeString(&unicodeString, EISA_DEVICE_NODE_NAME);
  76. status = IopCreateRegistryKeyEx( &deviceHandle,
  77. rootHandle,
  78. &unicodeString,
  79. KEY_ALL_ACCESS,
  80. REG_OPTION_NON_VOLATILE,
  81. NULL
  82. );
  83. ZwClose(rootHandle);
  84. if (!NT_SUCCESS(status)) {
  85. if (resourceList) {
  86. ExFreePool (resourceList);
  87. }
  88. return status;
  89. }
  90. PiWstrToUnicodeString( &unicodeString, L"0000" );
  91. status = IopCreateRegistryKeyEx( &instanceHandle,
  92. deviceHandle,
  93. &unicodeString,
  94. KEY_ALL_ACCESS,
  95. REG_OPTION_NON_VOLATILE,
  96. &disposition );
  97. ZwClose(deviceHandle);
  98. if (NT_SUCCESS(status)) {
  99. //
  100. // If the key already exists because it was explicitly migrated
  101. // during textmode setup, we should still consider it a "new key".
  102. //
  103. if (disposition != REG_CREATED_NEW_KEY) {
  104. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  105. status = IopGetRegistryValue(instanceHandle,
  106. REGSTR_VALUE_MIGRATED,
  107. &keyValueInformation);
  108. if (NT_SUCCESS(status)) {
  109. if ((keyValueInformation->Type == REG_DWORD) &&
  110. (keyValueInformation->DataLength == sizeof(ULONG)) &&
  111. ((*(PULONG)KEY_VALUE_DATA(keyValueInformation)) != 0)) {
  112. disposition = REG_CREATED_NEW_KEY;
  113. }
  114. ExFreePool(keyValueInformation);
  115. PiWstrToUnicodeString(&unicodeString, REGSTR_VALUE_MIGRATED);
  116. ZwDeleteValueKey(instanceHandle, &unicodeString);
  117. }
  118. }
  119. if (disposition == REG_CREATED_NEW_KEY) {
  120. PiWstrToUnicodeString( &unicodeString, L"DeviceDesc" );
  121. wcsncpy(buffer, L"Device to report Eisa Slot Resources", sizeof(buffer) / sizeof(WCHAR));
  122. buffer[(sizeof(buffer) / sizeof(WCHAR)) - 1] = UNICODE_NULL;
  123. ZwSetValueKey(instanceHandle,
  124. &unicodeString,
  125. 0,
  126. REG_SZ,
  127. buffer,
  128. (ULONG)((wcslen(buffer) + 1) * sizeof(WCHAR))
  129. );
  130. PiWstrToUnicodeString( &unicodeString, L"HardwareID" );
  131. RtlZeroMemory(buffer, BUFFER_LENGTH * sizeof(WCHAR));
  132. wcsncpy(buffer, L"*Eisa_Resource_Device", sizeof(buffer) / sizeof(WCHAR));
  133. buffer[(sizeof(buffer) / sizeof(WCHAR)) - 1] = UNICODE_NULL;
  134. ZwSetValueKey(instanceHandle,
  135. &unicodeString,
  136. 0,
  137. REG_MULTI_SZ,
  138. buffer,
  139. (ULONG)((wcslen(buffer) + 2) * sizeof(WCHAR))
  140. );
  141. PiWstrToUnicodeString(&unicodeString, REGSTR_VALUE_CONFIG_FLAGS);
  142. tmpValue = 0;
  143. ZwSetValueKey(instanceHandle,
  144. &unicodeString,
  145. TITLE_INDEX_VALUE,
  146. REG_DWORD,
  147. &tmpValue,
  148. sizeof(tmpValue)
  149. );
  150. }
  151. PiWstrToUnicodeString( &unicodeString, REGSTR_KEY_LOGCONF );
  152. status = IopCreateRegistryKeyEx( &logConfHandle,
  153. instanceHandle,
  154. &unicodeString,
  155. KEY_ALL_ACCESS,
  156. REG_OPTION_NON_VOLATILE,
  157. NULL
  158. );
  159. ZwClose(instanceHandle);
  160. if (NT_SUCCESS(status)) {
  161. PiWstrToUnicodeString( &unicodeString, REGSTR_VAL_BOOTCONFIG );
  162. status = ZwSetValueKey(logConfHandle,
  163. &unicodeString,
  164. 0,
  165. REG_RESOURCE_LIST,
  166. resourceList,
  167. resourceLength
  168. );
  169. ZwClose(logConfHandle);
  170. }
  171. }
  172. if (resourceList) {
  173. ExFreePool (resourceList);
  174. }
  175. return status;
  176. }
  177. NTSTATUS
  178. EisaGetEisaDevicesResources (
  179. OUT PCM_RESOURCE_LIST *ResourceList,
  180. OUT PULONG ResourceLength
  181. )
  182. /*++
  183. Routine Description:
  184. This routine builds a cm resource list for all the eisa slots.
  185. Arguments:
  186. None.
  187. Return Value:
  188. A CmResourceList.
  189. --*/
  190. {
  191. NTSTATUS status = STATUS_SUCCESS;
  192. HANDLE handle;
  193. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  194. UNICODE_STRING unicodeString;
  195. ULONG slotMasks = 0, numberMasks = 0, i;
  196. *ResourceList = NULL;
  197. *ResourceLength = 0;
  198. //
  199. // Open LocalMachine\Hardware\Description
  200. //
  201. //PiWstrToUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\EisaAdapter\\0");
  202. PiWstrToUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\EisaAdapter");
  203. status = IopOpenRegistryKeyEx( &handle,
  204. NULL,
  205. &unicodeString,
  206. KEY_READ
  207. );
  208. if (NT_SUCCESS(status)) {
  209. status = IopGetRegistryValue(handle,
  210. L"Configuration Data",
  211. &keyValueInformation
  212. );
  213. if (NT_SUCCESS(status)) {
  214. PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor;
  215. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDescriptor;
  216. resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
  217. ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset);
  218. if ((keyValueInformation->DataLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) &&
  219. (resourceDescriptor->PartialResourceList.Count > 0) ) {
  220. LONG eisaInfoLength;
  221. PCM_EISA_SLOT_INFORMATION eisaInfo;
  222. partialResourceDescriptor = resourceDescriptor->PartialResourceList.PartialDescriptors;
  223. if (partialResourceDescriptor->Type == CmResourceTypeDeviceSpecific) {
  224. eisaInfo = (PCM_EISA_SLOT_INFORMATION)
  225. ((PUCHAR)partialResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  226. eisaInfoLength = (LONG)partialResourceDescriptor->u.DeviceSpecificData.DataSize;
  227. //
  228. // Parse the eisa slot info to find the eisa slots with device installed.
  229. //
  230. for (i = 0; i < 0x10 && eisaInfoLength > 0; i++) {
  231. if (eisaInfo->ReturnCode == EISA_INVALID_SLOT) {
  232. break;
  233. }
  234. if (eisaInfo->ReturnCode != EISA_EMPTY_SLOT && (i != 0)) {
  235. slotMasks |= (1 << i);
  236. numberMasks++;
  237. }
  238. if (eisaInfo->ReturnCode == EISA_EMPTY_SLOT) {
  239. eisaInfoLength -= sizeof(CM_EISA_SLOT_INFORMATION);
  240. eisaInfo++;
  241. } else {
  242. eisaInfoLength -= sizeof(CM_EISA_SLOT_INFORMATION) + eisaInfo->NumberFunctions * sizeof(CM_EISA_FUNCTION_INFORMATION);
  243. eisaInfo = (PCM_EISA_SLOT_INFORMATION)
  244. ((PUCHAR)eisaInfo + eisaInfo->NumberFunctions * sizeof(CM_EISA_FUNCTION_INFORMATION) +
  245. sizeof(CM_EISA_SLOT_INFORMATION));
  246. }
  247. }
  248. if (slotMasks) {
  249. status = EisaBuildSlotsResources(slotMasks, numberMasks, ResourceList, ResourceLength);
  250. }
  251. }
  252. }
  253. ExFreePool(keyValueInformation);
  254. }
  255. ZwClose(handle);
  256. }
  257. return status;
  258. }
  259. NTSTATUS
  260. EisaBuildSlotsResources (
  261. IN ULONG SlotMasks,
  262. IN ULONG NumberMasks,
  263. OUT PCM_RESOURCE_LIST *Resources,
  264. OUT ULONG *Length
  265. )
  266. /*++
  267. Routine Description:
  268. This routine build a cm resource list for all the io resources used
  269. by the eisa devices.
  270. Arguments:
  271. SlotMask - a mask to indicate the valid eisa slot.
  272. Return Value:
  273. A pointer to a CM_RESOURCE_LIST.
  274. --*/
  275. {
  276. PCM_RESOURCE_LIST resources = NULL;
  277. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
  278. ULONG slot;
  279. *Length = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberMasks - 1);
  280. resources = ExAllocatePool(PagedPool, *Length);
  281. if (resources) {
  282. resources->Count = 1;
  283. resources->List[0].InterfaceType = Eisa;
  284. resources->List[0].BusNumber = 0;
  285. resources->List[0].PartialResourceList.Version = 0;
  286. resources->List[0].PartialResourceList.Revision = 0;
  287. resources->List[0].PartialResourceList.Count = NumberMasks;
  288. partialDesc = resources->List[0].PartialResourceList.PartialDescriptors;
  289. slot = 0; // ignore slot 0
  290. while (SlotMasks) {
  291. SlotMasks >>= 1;
  292. slot++;
  293. if (SlotMasks & 1) {
  294. partialDesc->Type = CmResourceTypePort;
  295. partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  296. partialDesc->Flags = CM_RESOURCE_PORT_16_BIT_DECODE + CM_RESOURCE_PORT_IO;
  297. partialDesc->u.Port.Start.LowPart = slot << 12;
  298. partialDesc->u.Port.Start.HighPart = 0;
  299. partialDesc->u.Port.Length = 0x1000;
  300. partialDesc++;
  301. }
  302. }
  303. *Resources = resources;
  304. return STATUS_SUCCESS;
  305. } else {
  306. return STATUS_NO_MEMORY;
  307. }
  308. }