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.

548 lines
14 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. PUCHAR baseAddress = NULL;
  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. PUCHAR kdBaseAddr = NULL;
  192. //
  193. // Get the information about headless
  194. //
  195. length = sizeof(HEADLESS_RSP_QUERY_INFO);
  196. status = HeadlessDispatch(HeadlessCmdQueryInformation,
  197. NULL,
  198. 0,
  199. &response,
  200. &length
  201. );
  202. if (NT_SUCCESS(status) &&
  203. (response.PortType == HeadlessSerialPort) &&
  204. response.Serial.TerminalAttached) {
  205. headlessBaseAddress = response.Serial.TerminalPortBaseAddress;
  206. }
  207. //
  208. // First of all, see if the any Kernel port is in use
  209. //
  210. if ((KdComPortInUse == NULL || *KdComPortInUse == 0) &&
  211. (headlessBaseAddress == NULL)) {
  212. //
  213. // No port in use
  214. //
  215. return;
  216. }
  217. if ( KdComPortInUse ) {
  218. kdBaseAddr = *KdComPortInUse;
  219. }
  220. //
  221. // Look through all the descriptors
  222. //
  223. while (count < Resources->dwDataLen) {
  224. //
  225. // We haven't found any IO ports
  226. //
  227. ioFound = FALSE;
  228. //
  229. // Determine the size of the PNP resource descriptor
  230. //
  231. if (!(tagName & LARGE_RESOURCE_TAG) ) {
  232. //
  233. // This is a small tag
  234. //
  235. increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1;
  236. tagName &= SMALL_TAG_MASK;
  237. } else {
  238. //
  239. // This is a large tag
  240. //
  241. increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3;
  242. }
  243. //
  244. // We are done if the current tag is the end tag
  245. //
  246. if (tagName == TAG_END) {
  247. break;
  248. }
  249. switch (tagName) {
  250. case TAG_IO: {
  251. PPNP_PORT_DESCRIPTOR desc = (PPNP_PORT_DESCRIPTOR) buffer;
  252. //
  253. // We found an IO port and so we will note that
  254. //
  255. baseAddress = (PUCHAR) ((ULONG_PTR)desc->MinimumAddress);
  256. ioFound = TRUE;
  257. break;
  258. }
  259. case TAG_IO_FIXED: {
  260. PPNP_FIXED_PORT_DESCRIPTOR desc = (PPNP_FIXED_PORT_DESCRIPTOR) buffer;
  261. //
  262. // We found an IO port so we will note that
  263. //
  264. baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress & 0x3FF));
  265. ioFound = TRUE;
  266. break;
  267. }
  268. case TAG_WORD_ADDRESS: {
  269. PPNP_WORD_ADDRESS_DESCRIPTOR desc = (PPNP_WORD_ADDRESS_DESCRIPTOR) buffer;
  270. //
  271. // Determine the address type
  272. //
  273. switch (desc->RFlag) {
  274. case PNP_ADDRESS_MEMORY_TYPE:
  275. //
  276. // We found a Mem IO Port
  277. //
  278. if ( kdBaseAddr ) {
  279. kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
  280. }
  281. //
  282. // fall through to the IO behavior.
  283. // The MinimumAddress will contain the memIO
  284. // address.
  285. //
  286. case PNP_ADDRESS_IO_TYPE:
  287. //
  288. // We found an IO Port, so we will note that
  289. //
  290. baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress +
  291. desc->TranslationAddress));
  292. ioFound = TRUE;
  293. break;
  294. default:
  295. NOTHING;
  296. break;
  297. }
  298. break;
  299. }
  300. case TAG_DOUBLE_ADDRESS: {
  301. PPNP_DWORD_ADDRESS_DESCRIPTOR desc = (PPNP_DWORD_ADDRESS_DESCRIPTOR) buffer;
  302. //
  303. // Determine the address type
  304. //
  305. switch (desc->RFlag) {
  306. case PNP_ADDRESS_MEMORY_TYPE:
  307. //
  308. // We found a Mem IO Port
  309. //
  310. if ( kdBaseAddr ) {
  311. kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
  312. }
  313. //
  314. // fall through to the IO behavior.
  315. // The MinimumAddress will contain the memIO
  316. // address.
  317. //
  318. case PNP_ADDRESS_IO_TYPE:
  319. //
  320. // We found an IO Port, so we will note that
  321. //
  322. baseAddress = (PUCHAR)((ULONG_PTR)(desc->MinimumAddress +
  323. desc->TranslationAddress));
  324. ioFound = TRUE;
  325. break;
  326. default:
  327. NOTHING;
  328. break;
  329. }
  330. break;
  331. }
  332. case TAG_QUAD_ADDRESS: {
  333. PPNP_QWORD_ADDRESS_DESCRIPTOR desc = (PPNP_QWORD_ADDRESS_DESCRIPTOR) buffer;
  334. //
  335. // Determine the address type
  336. //
  337. switch (desc->RFlag) {
  338. case PNP_ADDRESS_MEMORY_TYPE:
  339. //
  340. // We found a Mem IO Port
  341. //
  342. if ( kdBaseAddr ) {
  343. kdBaseAddr = (PUCHAR)((MmGetPhysicalAddress(kdBaseAddr)).QuadPart);
  344. }
  345. //
  346. // fall through to the IO behavior.
  347. // The MinimumAddress will contain the memIO
  348. // address.
  349. //
  350. case PNP_ADDRESS_IO_TYPE:
  351. //
  352. // We found an IO Port, so we will note that
  353. //
  354. baseAddress = (PUCHAR) (desc->MinimumAddress +
  355. desc->TranslationAddress);
  356. ioFound = TRUE;
  357. break;
  358. default:
  359. NOTHING;
  360. break;
  361. }
  362. break;
  363. }
  364. } // switch
  365. //
  366. // Did we find an IO port?
  367. //
  368. if (ioFound == TRUE) {
  369. //
  370. // Does the minimum address match?
  371. //
  372. if (((KdComPortInUse != NULL) && (baseAddress == kdBaseAddr)) ||
  373. ((headlessBaseAddress != NULL) && (baseAddress == headlessBaseAddress))) {
  374. //
  375. // Mark the node as being special
  376. //
  377. ACPIInternalUpdateFlags(
  378. &(DeviceExtension->Flags),
  379. (DEV_CAP_NO_OVERRIDE | DEV_CAP_NO_STOP | DEV_CAP_ALWAYS_PS0 |
  380. DEV_TYPE_NOT_PRESENT | DEV_TYPE_NEVER_PRESENT),
  381. FALSE);
  382. if ((KdComPortInUse != NULL) && (baseAddress == kdBaseAddr)) {
  383. ACPIDevPrint( (
  384. ACPI_PRINT_LOADING,
  385. DeviceExtension,
  386. "ACPIMatchKernelPorts - Found KD Port at %lx\n",
  387. baseAddress
  388. ) );
  389. } else {
  390. ACPIDevPrint( (
  391. ACPI_PRINT_LOADING,
  392. DeviceExtension,
  393. "ACPIMatchKernelPorts - Found Headless Port at %lx\n",
  394. baseAddress
  395. ) );
  396. }
  397. break;
  398. }
  399. }
  400. //
  401. // Move of the next descriptor
  402. //
  403. count += increment;
  404. buffer += increment;
  405. tagName = *buffer;
  406. }
  407. }