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.

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