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.

470 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. match.c
  5. Abstract:
  6. This module contains the routines that try to match a PNSOBJ with a DeviceObject
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Model Driver only
  11. --*/
  12. #include "pch.h"
  13. #include "hdlsblk.h"
  14. #include "hdlsterm.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE,ACPIMatchHardwareAddress)
  17. #pragma alloc_text(PAGE,ACPIMatchHardwareId)
  18. #endif
  19. NTSTATUS
  20. ACPIMatchHardwareAddress(
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN ULONG DeviceAddress,
  23. OUT BOOLEAN *Success
  24. )
  25. /*++
  26. Routine Description:
  27. This routine determines the device address of the two supplied objects and checks
  28. for a match
  29. Arguments:
  30. DeviceObject - The NT DeviceObject that we wish to check
  31. DeviceAddress - The ACPI address of the device
  32. Success - Pointer of where to store the result of the comparison
  33. Return Value:
  34. NTSTATUS
  35. --*/
  36. {
  37. DEVICE_CAPABILITIES deviceCapabilities;
  38. NTSTATUS status;
  39. PAGED_CODE();
  40. ASSERT( DeviceObject != NULL );
  41. ASSERT( Success != NULL );
  42. //
  43. // Assume that we don't succeed
  44. //
  45. *Success = FALSE;
  46. //
  47. // Get the capabilities
  48. //
  49. status = ACPIInternalGetDeviceCapabilities(
  50. DeviceObject,
  51. &deviceCapabilities
  52. );
  53. if (!NT_SUCCESS(status)) {
  54. goto ACPIMatchHardwareAddressExit;
  55. }
  56. //
  57. // Lets compare the two answers
  58. //
  59. ACPIPrint( (
  60. ACPI_PRINT_LOADING,
  61. "%lx: ACPIMatchHardwareAddress - Device %08lx - %08lx\n",
  62. DeviceAddress,
  63. DeviceObject,
  64. deviceCapabilities.Address
  65. ) );
  66. if (DeviceAddress == deviceCapabilities.Address) {
  67. *Success = TRUE;
  68. }
  69. ACPIMatchHardwareAddressExit:
  70. ACPIPrint( (
  71. ACPI_PRINT_LOADING,
  72. "%lx: ACPIMatchHardwareAddress - Device: %#08lx - Status: %#08lx "
  73. "Success:%#02lx\n",
  74. DeviceAddress,
  75. DeviceObject,
  76. status,
  77. *Success
  78. ) );
  79. return status;
  80. }
  81. NTSTATUS
  82. ACPIMatchHardwareId(
  83. IN PDEVICE_OBJECT DeviceObject,
  84. IN PUNICODE_STRING AcpiUnicodeId,
  85. OUT BOOLEAN *Success
  86. )
  87. /*++
  88. Routine Description:
  89. This routine is responsible for determining if the supplied objects have the
  90. same device name
  91. Arguments:
  92. DeviceObject - The NT Device Object whose name we want to check
  93. UnicodeId - The ID that we are trying to match with
  94. Success - Where to store the success status
  95. Return Value:
  96. NTSTATUS
  97. --*/
  98. {
  99. IO_STACK_LOCATION irpSp;
  100. NTSTATUS status;
  101. PWSTR buffer;
  102. PWSTR currentPtr;
  103. UNICODE_STRING objectDeviceId;
  104. PAGED_CODE();
  105. ASSERT( DeviceObject != NULL );
  106. ASSERT( Success != NULL );
  107. *Success = FALSE;
  108. //
  109. // Initialize the stack location to pass to ACPIInternalSendSynchronousIrp()
  110. //
  111. RtlZeroMemory( &irpSp, sizeof(IO_STACK_LOCATION) );
  112. RtlZeroMemory( &objectDeviceId, sizeof(UNICODE_STRING) );
  113. //
  114. // Set the function codes
  115. //
  116. irpSp.MajorFunction = IRP_MJ_PNP;
  117. irpSp.MinorFunction = IRP_MN_QUERY_ID;
  118. irpSp.Parameters.QueryId.IdType = BusQueryHardwareIDs;
  119. //
  120. // Make the call now...
  121. //
  122. status = ACPIInternalSendSynchronousIrp( DeviceObject, &irpSp, &buffer );
  123. if (!NT_SUCCESS(status)) {
  124. goto ACPIMatchHardwareIdExit;
  125. }
  126. //
  127. // The return from the call is actually a MultiString, so we have to
  128. // walk all of its components
  129. //
  130. currentPtr = buffer;
  131. while (currentPtr && *currentPtr != L'\0') {
  132. //
  133. // At this point, we can make a Unicode String from the buffer...
  134. //
  135. RtlInitUnicodeString( &objectDeviceId, currentPtr );
  136. //
  137. // Increment the current pointer to the next part of the MultiString
  138. //
  139. currentPtr += (objectDeviceId.MaximumLength / sizeof(WCHAR) );
  140. //
  141. // Now try to compare the two unicode strings...
  142. //
  143. if (RtlEqualUnicodeString( &objectDeviceId, AcpiUnicodeId, TRUE) ) {
  144. *Success = TRUE;
  145. break;
  146. }
  147. }
  148. //
  149. // Done -- free resources
  150. //
  151. ExFreePool( buffer );
  152. ACPIMatchHardwareIdExit:
  153. ACPIPrint( (
  154. ACPI_PRINT_LOADING,
  155. "%ws: ACPIMatchHardwareId - %08lx - Status: %#08lx Success:%#02lx\n",
  156. AcpiUnicodeId->Buffer,
  157. DeviceObject,
  158. status,
  159. *Success
  160. ) );
  161. return status;
  162. }
  163. VOID
  164. ACPIMatchKernelPorts(
  165. IN PDEVICE_EXTENSION DeviceExtension,
  166. IN POBJDATA Resources
  167. )
  168. /*++
  169. Routine Description:
  170. This routine is called to determine if the supplied deviceExtension
  171. is currently in use by the Kernel as the debugger port or the headless
  172. port. If it is so marked, then we handle it 'special'.
  173. Arguments:
  174. DeviceExtension - Port to check
  175. Resources - What resources the port is using
  176. Return Value:
  177. None
  178. --*/
  179. {
  180. BOOLEAN ioFound;
  181. BOOLEAN matchFound = FALSE;
  182. PUCHAR buffer = Resources->pbDataBuff;
  183. UCHAR tagName = *buffer;
  184. ULONG baseAddress = 0;
  185. ULONG count = 0;
  186. PUCHAR headlessBaseAddress = NULL;
  187. USHORT increment;
  188. SIZE_T length;
  189. NTSTATUS status;
  190. HEADLESS_RSP_QUERY_INFO response;
  191. //
  192. // Get the information about headless
  193. //
  194. length = sizeof(HEADLESS_RSP_QUERY_INFO);
  195. status = HeadlessDispatch(HeadlessCmdQueryInformation,
  196. NULL,
  197. 0,
  198. &response,
  199. &length
  200. );
  201. if (NT_SUCCESS(status) &&
  202. (response.PortType == HeadlessSerialPort) &&
  203. response.Serial.TerminalAttached) {
  204. headlessBaseAddress = response.Serial.TerminalPortBaseAddress;
  205. }
  206. //
  207. // First of all, see if the any Kernel port is in use
  208. //
  209. if ((KdComPortInUse == NULL || *KdComPortInUse == 0) &&
  210. (headlessBaseAddress == NULL)) {
  211. //
  212. // No port in use
  213. //
  214. return;
  215. }
  216. //
  217. // Look through all the descriptors
  218. //
  219. while (count < Resources->dwDataLen) {
  220. //
  221. // We haven't found any IO ports
  222. //
  223. ioFound = FALSE;
  224. //
  225. // Determine the size of the PNP resource descriptor
  226. //
  227. if (!(tagName & LARGE_RESOURCE_TAG) ) {
  228. //
  229. // This is a small tag
  230. //
  231. increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1;
  232. tagName &= SMALL_TAG_MASK;
  233. } else {
  234. //
  235. // This is a large tag
  236. //
  237. increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3;
  238. }
  239. //
  240. // We are done if the current tag is the end tag
  241. //
  242. if (tagName == TAG_END) {
  243. break;
  244. }
  245. switch (tagName) {
  246. case TAG_IO: {
  247. PPNP_PORT_DESCRIPTOR desc = (PPNP_PORT_DESCRIPTOR) buffer;
  248. //
  249. // We found an IO port and so we will note that
  250. //
  251. baseAddress = (ULONG) desc->MinimumAddress;
  252. ioFound = TRUE;
  253. break;
  254. }
  255. case TAG_IO_FIXED: {
  256. PPNP_FIXED_PORT_DESCRIPTOR desc = (PPNP_FIXED_PORT_DESCRIPTOR) buffer;
  257. //
  258. // We found an IO port so we will note that
  259. //
  260. baseAddress = (ULONG) (desc->MinimumAddress & 0x3FF);
  261. ioFound = TRUE;
  262. break;
  263. }
  264. case TAG_WORD_ADDRESS: {
  265. PPNP_WORD_ADDRESS_DESCRIPTOR desc = (PPNP_WORD_ADDRESS_DESCRIPTOR) buffer;
  266. //
  267. // Is this an IO port?
  268. //
  269. if (desc->RFlag == PNP_ADDRESS_IO_TYPE) {
  270. //
  271. // We found an IO port, so we will note that
  272. //
  273. baseAddress = (ULONG) desc->MinimumAddress +
  274. desc->TranslationAddress;
  275. ioFound = TRUE;
  276. }
  277. break;
  278. }
  279. case TAG_DOUBLE_ADDRESS: {
  280. PPNP_DWORD_ADDRESS_DESCRIPTOR desc = (PPNP_DWORD_ADDRESS_DESCRIPTOR) buffer;
  281. //
  282. // If this an IO port
  283. //
  284. if (desc->RFlag == PNP_ADDRESS_IO_TYPE) {
  285. //
  286. // We found an IO Port, so we will note that
  287. //
  288. baseAddress = (ULONG) desc->MinimumAddress +
  289. desc->TranslationAddress;
  290. ioFound = TRUE;
  291. }
  292. break;
  293. }
  294. case TAG_QUAD_ADDRESS: {
  295. PPNP_QWORD_ADDRESS_DESCRIPTOR desc = (PPNP_QWORD_ADDRESS_DESCRIPTOR) buffer;
  296. //
  297. // If this an IO port
  298. //
  299. if (desc->RFlag == PNP_ADDRESS_IO_TYPE) {
  300. //
  301. // We found an IO Port, so we will note that
  302. //
  303. baseAddress = (ULONG) (desc->MinimumAddress +
  304. desc->TranslationAddress);
  305. ioFound = TRUE;
  306. }
  307. break;
  308. }
  309. } // switch
  310. //
  311. // Did we find an IO port?
  312. //
  313. if (ioFound == TRUE) {
  314. //
  315. // Does the minimum address match?
  316. //
  317. if (((KdComPortInUse != NULL) && (baseAddress == (ULONG_PTR) *KdComPortInUse)) ||
  318. ((headlessBaseAddress != NULL) && (baseAddress == (ULONG_PTR)headlessBaseAddress))) {
  319. //
  320. // Mark the node as being special
  321. //
  322. ACPIInternalUpdateFlags(
  323. &(DeviceExtension->Flags),
  324. (DEV_CAP_NO_OVERRIDE | DEV_CAP_NO_STOP | DEV_CAP_ALWAYS_PS0 |
  325. DEV_TYPE_NOT_PRESENT | DEV_TYPE_NEVER_PRESENT),
  326. FALSE);
  327. if ((KdComPortInUse != NULL) && (baseAddress == (ULONG_PTR) *KdComPortInUse)) {
  328. ACPIDevPrint( (
  329. ACPI_PRINT_LOADING,
  330. DeviceExtension,
  331. "ACPIMatchKernelPorts - Found KD Port at %lx\n",
  332. baseAddress
  333. ) );
  334. } else {
  335. ACPIDevPrint( (
  336. ACPI_PRINT_LOADING,
  337. DeviceExtension,
  338. "ACPIMatchKernelPorts - Found Headless Port at %lx\n",
  339. baseAddress
  340. ) );
  341. }
  342. break;
  343. }
  344. }
  345. //
  346. // Move of the next descriptor
  347. //
  348. count += increment;
  349. buffer += increment;
  350. tagName = *buffer;
  351. }
  352. }