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.

563 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ixusage.c
  5. Abstract:
  6. Author:
  7. Ken Reneris (kenr)
  8. Environment:
  9. Kernel mode only.
  10. Revision History:
  11. --*/
  12. #include "halp.h"
  13. #include "kdcom.h"
  14. //
  15. // Array to remember hal's IDT usage
  16. //
  17. extern ADDRESS_USAGE *HalpAddressUsageList;
  18. extern IDTUsage HalpIDTUsage[];
  19. extern KAFFINITY HalpActiveProcessors;
  20. extern ULONG HalDisableFirmwareMapper;
  21. PUCHAR KdComPortInUse = NULL;
  22. ADDRESS_USAGE HalpComIoSpace = {
  23. NULL, CmResourceTypePort, DeviceUsage,
  24. {
  25. 0x2F8, 0x8, // Default is 2F8 for COM2. This will be changed.
  26. 0, 0
  27. }
  28. };
  29. VOID
  30. HalpGetResourceSortValue (
  31. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
  32. OUT PULONG sortscale,
  33. OUT PLARGE_INTEGER sortvalue
  34. );
  35. VOID
  36. HalpMarkAcpiHal(
  37. VOID
  38. );
  39. USHORT HalpComPortIrqMapping[5][2] = {
  40. {COM1_PORT, 4},
  41. {COM2_PORT, 3},
  42. {COM3_PORT, 4},
  43. {COM4_PORT, 3},
  44. {0,0}
  45. };
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text(INIT,HalpRegisterVector)
  48. #pragma alloc_text(INIT,HalpGetResourceSortValue)
  49. #pragma alloc_text(INIT,HalpReportResourceUsage)
  50. #pragma alloc_text(PAGE, HalpMarkAcpiHal)
  51. #endif
  52. VOID
  53. HalpRegisterVector (
  54. IN UCHAR ReportFlags,
  55. IN ULONG BusInterruptVector,
  56. IN ULONG SystemInterruptVector,
  57. IN KIRQL SystemIrql
  58. )
  59. /*++
  60. Routine Description:
  61. This registers an IDT vectors usage by the HAL.
  62. Arguments:
  63. Return Value:
  64. --*/
  65. {
  66. #if DBG
  67. // There are only 0ff IDT entries...
  68. ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
  69. BusInterruptVector <= MAXIMUM_IDTVECTOR);
  70. #endif
  71. //
  72. // Remember which vector the hal is connecting so it can be reported
  73. // later on
  74. //
  75. HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
  76. HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
  77. HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
  78. }
  79. VOID
  80. HalpGetResourceSortValue (
  81. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
  82. OUT PULONG sortscale,
  83. OUT PLARGE_INTEGER sortvalue
  84. )
  85. /*++
  86. Routine Description:
  87. Used by HalpReportResourceUsage in order to properly sort
  88. partial_resource_descriptors.
  89. Arguments:
  90. pRCurLoc - resource descriptor
  91. Return Value:
  92. sortscale - scaling of resource descriptor for sorting
  93. sortvalue - value to sort on
  94. --*/
  95. {
  96. switch (pRCurLoc->Type) {
  97. case CmResourceTypeInterrupt:
  98. *sortscale = 0;
  99. *sortvalue = RtlConvertUlongToLargeInteger(
  100. pRCurLoc->u.Interrupt.Level );
  101. break;
  102. case CmResourceTypePort:
  103. *sortscale = 1;
  104. *sortvalue = pRCurLoc->u.Port.Start;
  105. break;
  106. case CmResourceTypeMemory:
  107. *sortscale = 2;
  108. *sortvalue = pRCurLoc->u.Memory.Start;
  109. break;
  110. default:
  111. *sortscale = 4;
  112. *sortvalue = RtlConvertUlongToLargeInteger (0);
  113. break;
  114. }
  115. }
  116. VOID
  117. HalpReportResourceUsage (
  118. IN PUNICODE_STRING HalName,
  119. IN INTERFACE_TYPE DeviceInterfaceToUse
  120. )
  121. /*++
  122. Routine Description:
  123. Arguments:
  124. Return Value:
  125. --*/
  126. {
  127. PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
  128. PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
  129. PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
  130. PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
  131. PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
  132. CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
  133. ULONG i, j, k, ListSize, Count;
  134. ULONG curscale, sortscale;
  135. UCHAR pass, reporton;
  136. INTERFACE_TYPE interfacetype;
  137. ULONG CurrentIDT, CurrentElement;
  138. ADDRESS_USAGE *CurrentAddress;
  139. LARGE_INTEGER curvalue, sortvalue;
  140. //
  141. // Claim the debugger com port resource if it is in use
  142. //
  143. if (KdComPortInUse != NULL) {
  144. HalpComIoSpace.Element[0].Start = (ULONG)(ULONG_PTR)KdComPortInUse;
  145. HalpRegisterAddressUsage(&HalpComIoSpace);
  146. //
  147. // The debugger does not use any interrupts. However for consistent
  148. // behaviour between a machine with and without a debugger, we claim
  149. // an interrupt for the debugger if the debugger port address is one
  150. // for COM1-4.
  151. //
  152. for (i = 0; HalpComPortIrqMapping[i][0]; i++) {
  153. if ((PUCHAR)HalpComPortIrqMapping[i][0] == KdComPortInUse) {
  154. HalpRegisterVector( DeviceUsage | InterruptLatched,
  155. HalpComPortIrqMapping[i][1],
  156. HalpComPortIrqMapping[i][1] +
  157. PRIMARY_VECTOR_BASE,
  158. HIGH_LEVEL);
  159. break;
  160. }
  161. }
  162. }
  163. //
  164. // Allocate some space to build the resource structure
  165. //
  166. RawResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
  167. NonPagedPool,
  168. PAGE_SIZE*2,
  169. HAL_POOL_TAG);
  170. TranslatedResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
  171. NonPagedPool,
  172. PAGE_SIZE*2,
  173. HAL_POOL_TAG);
  174. if (!RawResourceList || !TranslatedResourceList) {
  175. //
  176. // These allocations were critical.
  177. //
  178. KeBugCheckEx(HAL_MEMORY_ALLOCATION,
  179. PAGE_SIZE*4,
  180. 1,
  181. (UINT_PTR)__FILE__,
  182. __LINE__
  183. );
  184. }
  185. //
  186. // This functions assumes unset fields are zero
  187. //
  188. RtlZeroMemory(RawResourceList, PAGE_SIZE*2);
  189. RtlZeroMemory(TranslatedResourceList, PAGE_SIZE*2);
  190. //
  191. // Initialize the lists
  192. //
  193. RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
  194. pRFullDesc = RawResourceList->List;
  195. pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
  196. pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
  197. for(pass=0; pass < 2; pass++) {
  198. if (pass == 0) {
  199. //
  200. // First pass - build resource lists for resources reported
  201. // reported against device usage.
  202. //
  203. reporton = DeviceUsage & ~IDTOwned;
  204. interfacetype = DeviceInterfaceToUse;
  205. } else {
  206. //
  207. // Second pass = build reousce lists for resources reported
  208. // as internal usage.
  209. //
  210. reporton = InternalUsage & ~IDTOwned;
  211. interfacetype = Internal;
  212. }
  213. CurrentIDT = 0;
  214. CurrentElement = 0;
  215. CurrentAddress = HalpAddressUsageList;
  216. for (; ;) {
  217. if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
  218. //
  219. // Check to see if CurrentIDT needs to be reported
  220. //
  221. if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
  222. // Don't report on this one
  223. CurrentIDT++;
  224. continue;
  225. }
  226. //
  227. // Report CurrentIDT resource
  228. //
  229. RPartialDesc.Type = CmResourceTypeInterrupt;
  230. RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
  231. RPartialDesc.Flags =
  232. HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
  233. CM_RESOURCE_INTERRUPT_LATCHED :
  234. CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  235. RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
  236. RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
  237. RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
  238. RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
  239. TPartialDesc.u.Interrupt.Vector = CurrentIDT;
  240. TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
  241. CurrentIDT++;
  242. } else {
  243. //
  244. // Check to see if CurrentAddress needs to be reported
  245. //
  246. if (!CurrentAddress) {
  247. break; // No addresses left
  248. }
  249. if (!(CurrentAddress->Flags & reporton)) {
  250. // Don't report on this list
  251. CurrentElement = 0;
  252. CurrentAddress = CurrentAddress->Next;
  253. continue;
  254. }
  255. if (!CurrentAddress->Element[CurrentElement].Length) {
  256. // End of current list, go to next list
  257. CurrentElement = 0;
  258. CurrentAddress = CurrentAddress->Next;
  259. continue;
  260. }
  261. //
  262. // Report CurrentAddress
  263. //
  264. RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
  265. RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
  266. if (RPartialDesc.Type == CmResourceTypePort) {
  267. i = 1; // address space port
  268. RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
  269. } else {
  270. i = 0; // address space memory
  271. RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  272. }
  273. // Notice: assuming u.Memory and u.Port have the same layout
  274. RPartialDesc.u.Memory.Start.HighPart = 0;
  275. RPartialDesc.u.Memory.Start.LowPart =
  276. CurrentAddress->Element[CurrentElement].Start;
  277. RPartialDesc.u.Memory.Length =
  278. CurrentAddress->Element[CurrentElement].Length;
  279. // translated address = Raw address
  280. RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
  281. HalTranslateBusAddress (
  282. interfacetype, // device bus or internal
  283. 0, // bus number
  284. RPartialDesc.u.Memory.Start, // source address
  285. &i, // address space
  286. &TPartialDesc.u.Memory.Start ); // translated address
  287. if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
  288. TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
  289. }
  290. CurrentElement++;
  291. }
  292. //
  293. // Include the current resource in the HALs list
  294. //
  295. if (pRFullDesc->InterfaceType != interfacetype) {
  296. //
  297. // Interface type changed, add another full section
  298. //
  299. RawResourceList->Count++;
  300. TranslatedResourceList->Count++;
  301. pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
  302. pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
  303. pRFullDesc->InterfaceType = interfacetype;
  304. pTFullDesc->InterfaceType = interfacetype;
  305. pRPartList = &pRFullDesc->PartialResourceList;
  306. pTPartList = &pTFullDesc->PartialResourceList;
  307. //
  308. // Bump current location pointers up
  309. //
  310. pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
  311. pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
  312. }
  313. pRPartList->Count++;
  314. pTPartList->Count++;
  315. RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
  316. RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
  317. pRCurLoc++;
  318. pTCurLoc++;
  319. }
  320. }
  321. ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
  322. //
  323. // The HAL's resource usage structures have been built
  324. // Sort the partial lists based on the Raw resource values
  325. //
  326. pRFullDesc = RawResourceList->List;
  327. pTFullDesc = TranslatedResourceList->List;
  328. for (i=0; i < RawResourceList->Count; i++) {
  329. pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
  330. pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
  331. Count = pRFullDesc->PartialResourceList.Count;
  332. for (j=0; j < Count; j++) {
  333. HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
  334. pRSortLoc = pRCurLoc;
  335. pTSortLoc = pTCurLoc;
  336. for (k=j; k < Count; k++) {
  337. HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
  338. if (sortscale < curscale ||
  339. (sortscale == curscale &&
  340. RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
  341. //
  342. // Swap the elements..
  343. //
  344. RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
  345. RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
  346. RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
  347. // swap translated descriptor as well
  348. RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
  349. RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
  350. RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
  351. // get new curscale & curvalue
  352. HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
  353. }
  354. pRSortLoc++;
  355. pTSortLoc++;
  356. }
  357. pRCurLoc++;
  358. pTCurLoc++;
  359. }
  360. pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
  361. pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
  362. }
  363. HalpMarkAcpiHal();
  364. //
  365. // Inform the IO system of our resources..
  366. //
  367. IoReportHalResourceUsage (
  368. HalName,
  369. RawResourceList,
  370. TranslatedResourceList,
  371. ListSize
  372. );
  373. ExFreePool (RawResourceList);
  374. ExFreePool (TranslatedResourceList);
  375. }
  376. VOID
  377. HalpMarkAcpiHal(
  378. VOID
  379. )
  380. /*++
  381. Routine Description:
  382. Arguments:
  383. None.
  384. Return Value:
  385. None.
  386. --*/
  387. {
  388. UNICODE_STRING unicodeString;
  389. HANDLE hCurrentControlSet, handle;
  390. NTSTATUS status;
  391. PAGED_CODE();
  392. //
  393. // Open/create System\CurrentControlSet key.
  394. //
  395. RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
  396. status = HalpOpenRegistryKey (
  397. &hCurrentControlSet,
  398. NULL,
  399. &unicodeString,
  400. KEY_ALL_ACCESS,
  401. FALSE
  402. );
  403. if (!NT_SUCCESS(status)) {
  404. return;
  405. }
  406. //
  407. // Open HKLM\System\CurrentControlSet\Control\Pnp
  408. //
  409. RtlInitUnicodeString(&unicodeString, L"Control\\Pnp");
  410. status = HalpOpenRegistryKey (
  411. &handle,
  412. hCurrentControlSet,
  413. &unicodeString,
  414. KEY_ALL_ACCESS,
  415. TRUE
  416. );
  417. ZwClose(hCurrentControlSet);
  418. if (!NT_SUCCESS(status)) {
  419. return;
  420. }
  421. RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper");
  422. ZwSetValueKey(handle,
  423. &unicodeString,
  424. 0,
  425. REG_DWORD,
  426. &HalDisableFirmwareMapper,
  427. sizeof(HalDisableFirmwareMapper)
  428. );
  429. ZwClose(handle);
  430. }