Windows NT 4.0 source code leak
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.

680 lines
16 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. devres.c
  5. Abstract:
  6. This module contains the high level device resources support routines.
  7. Author:
  8. Shie-Lin Tzong (shielint) July-27-1995
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "busp.h"
  14. #include "pnpisa.h"
  15. #include "pbios.h"
  16. #define IDBG 0
  17. #pragma alloc_text(INIT,PipGetCardIdentifier)
  18. #pragma alloc_text(INIT,PipGetFunctionIdentifier)
  19. #pragma alloc_text(INIT,PipGetCompatibleDeviceId)
  20. #pragma alloc_text(INIT,PipQueryDeviceId)
  21. #pragma alloc_text(INIT,PipQueryDeviceUniqueId)
  22. #pragma alloc_text(INIT,PipQueryDeviceResources)
  23. #pragma alloc_text(INIT,PipQueryDeviceResourceRequirements)
  24. #pragma alloc_text(INIT,PipSetDeviceResources)
  25. NTSTATUS
  26. PipGetCardIdentifier (
  27. PUCHAR CardData,
  28. PWCHAR *Buffer,
  29. PULONG BufferLength
  30. )
  31. /*++
  32. Routine Description:
  33. This function returns the identifier for a pnpisa card.
  34. Arguments:
  35. CardData - supplies a pointer to the pnp isa device data.
  36. Buffer - supplies a pointer to variable to receive a pointer to the Id.
  37. BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
  38. Return Value:
  39. NTSTATUS code
  40. --*/
  41. {
  42. NTSTATUS status = STATUS_SUCCESS;
  43. UCHAR tag;
  44. LONG size, length;
  45. UNICODE_STRING unicodeString;
  46. ANSI_STRING ansiString;
  47. PCHAR ansiBuffer;
  48. *Buffer = NULL;
  49. *BufferLength = 0;
  50. tag = *CardData;
  51. //
  52. // Make sure CardData does *NOT* point to a Logical Device Id tag
  53. //
  54. if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
  55. DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n");
  56. return status;
  57. }
  58. //
  59. // Find the resource descriptor which describle identifier string
  60. //
  61. do {
  62. //
  63. // Do we find the identifer resource tag?
  64. //
  65. if (tag == TAG_ANSI_ID) {
  66. CardData++;
  67. length = *(PUSHORT)CardData;
  68. CardData += 2;
  69. ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
  70. if (ansiBuffer == NULL) {
  71. status = STATUS_INSUFFICIENT_RESOURCES;
  72. break;
  73. }
  74. RtlMoveMemory(ansiBuffer, CardData, length);
  75. ansiBuffer[length] = 0;
  76. RtlInitAnsiString(&ansiString, ansiBuffer);
  77. RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
  78. ExFreePool(ansiBuffer);
  79. *Buffer = unicodeString.Buffer;
  80. *BufferLength = unicodeString.Length + sizeof(WCHAR);
  81. break;
  82. }
  83. //
  84. // Determine the size of the BIOS resource descriptor and
  85. // advance to next resource descriptor.
  86. //
  87. if (!(tag & LARGE_RESOURCE_TAG)) {
  88. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  89. size += 1; // length of small tag
  90. } else {
  91. size = *(PUSHORT)(CardData + 1);
  92. size += 3; // length of large tag
  93. }
  94. CardData += size;
  95. tag = *CardData;
  96. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  97. return status;
  98. }
  99. NTSTATUS
  100. PipGetFunctionIdentifier (
  101. PUCHAR DeviceData,
  102. PWCHAR *Buffer,
  103. PULONG BufferLength
  104. )
  105. /*++
  106. Routine Description:
  107. This function returns the desired pnp isa identifier for the specified
  108. DeviceData/LogicalFunction. The Identifier for a logical function is
  109. optional. If no Identifier available , Buffer is set to NULL.
  110. Arguments:
  111. DeviceData - supplies a pointer to the pnp isa device data.
  112. Buffer - supplies a pointer to variable to receive a pointer to the Id.
  113. BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
  114. Return Value:
  115. NTSTATUS code
  116. --*/
  117. {
  118. NTSTATUS status = STATUS_SUCCESS;
  119. UCHAR tag;
  120. LONG size, length;
  121. UNICODE_STRING unicodeString;
  122. ANSI_STRING ansiString;
  123. PCHAR ansiBuffer;
  124. *Buffer = NULL;
  125. *BufferLength = 0;
  126. tag = *DeviceData;
  127. #if DBG
  128. //
  129. // Make sure device data points to Logical Device Id tag
  130. //
  131. if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
  132. DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n");
  133. }
  134. #endif
  135. //
  136. // Skip all the resource descriptors to find compatible Id descriptor
  137. //
  138. do {
  139. //
  140. // Determine the size of the BIOS resource descriptor and
  141. // advance to next resource descriptor.
  142. //
  143. if (!(tag & LARGE_RESOURCE_TAG)) {
  144. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  145. size += 1; // length of small tag
  146. } else {
  147. size = *(PUSHORT)(DeviceData + 1);
  148. size += 3; // length of large tag
  149. }
  150. DeviceData += size;
  151. tag = *DeviceData;
  152. //
  153. // Do we find the identifer resource tag?
  154. //
  155. if (tag == TAG_ANSI_ID) {
  156. DeviceData++;
  157. length = *(PUSHORT)DeviceData;
  158. DeviceData += 2;
  159. ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
  160. if (ansiBuffer == NULL) {
  161. status = STATUS_INSUFFICIENT_RESOURCES;
  162. break;
  163. }
  164. RtlMoveMemory(ansiBuffer, DeviceData, length);
  165. ansiBuffer[length] = 0;
  166. RtlInitAnsiString(&ansiString, ansiBuffer);
  167. RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
  168. ExFreePool(ansiBuffer);
  169. *Buffer = unicodeString.Buffer;
  170. *BufferLength = unicodeString.Length + sizeof(WCHAR);
  171. break;
  172. }
  173. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  174. return status;
  175. }
  176. NTSTATUS
  177. PipGetCompatibleDeviceId (
  178. PUCHAR DeviceData,
  179. ULONG IdIndex,
  180. PWCHAR *Buffer
  181. )
  182. /*++
  183. Routine Description:
  184. This function returns the desired pnp isa id for the specified DeviceData
  185. and Id index. If Id index = 0, the Hardware ID will be return; if id
  186. index = n, the Nth compatible id will be returned.
  187. Arguments:
  188. DeviceData - supplies a pointer to the pnp isa device data.
  189. IdIndex - supplies the index of the compatible id desired.
  190. Buffer - supplies a pointer to variable to receive a pointer to the compatible Id.
  191. Return Value:
  192. NTSTATUS code
  193. --*/
  194. {
  195. NTSTATUS status = STATUS_NO_MORE_ENTRIES;
  196. UCHAR tag;
  197. ULONG count = 0;
  198. LONG size;
  199. UNICODE_STRING unicodeString;
  200. ANSI_STRING ansiString;
  201. UCHAR eisaId[8];
  202. ULONG id;
  203. tag = *DeviceData;
  204. #if DBG
  205. //
  206. // Make sure device data points to Logical Device Id tag
  207. //
  208. if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
  209. DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
  210. }
  211. #endif
  212. if (IdIndex == 0) {
  213. //
  214. // Caller is asking for hardware id
  215. //
  216. DeviceData++; // Skip tag
  217. id = *(PULONG)DeviceData;
  218. status = STATUS_SUCCESS;
  219. } else {
  220. //
  221. // caller is asking for compatible id
  222. //
  223. IdIndex--;
  224. //
  225. // Skip all the resource descriptors to find compatible Id descriptor
  226. //
  227. do {
  228. //
  229. // Determine the size of the BIOS resource descriptor and
  230. // advance to next resource descriptor.
  231. //
  232. if (!(tag & LARGE_RESOURCE_TAG)) {
  233. size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
  234. size += 1; // length of small tag
  235. } else {
  236. size = *(PUSHORT)(DeviceData + 1);
  237. size += 3; // length of large tag
  238. }
  239. DeviceData += size;
  240. tag = *DeviceData;
  241. //
  242. // Do we reach the compatible ID descriptor?
  243. //
  244. if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
  245. if (count == IdIndex) {
  246. id = *(PULONG)(DeviceData + 1);
  247. status = STATUS_SUCCESS;
  248. break;
  249. } else {
  250. count++;
  251. }
  252. }
  253. } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
  254. }
  255. if (NT_SUCCESS(status)) {
  256. PipDecompressEisaId(id, eisaId);
  257. RtlInitAnsiString(&ansiString, eisaId);
  258. RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
  259. *Buffer = (PWCHAR)ExAllocatePool (
  260. PagedPool,
  261. sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length
  262. );
  263. if (*Buffer) {
  264. swprintf(*Buffer, L"*%s", unicodeString.Buffer);
  265. } else {
  266. status = STATUS_INSUFFICIENT_RESOURCES;
  267. }
  268. RtlFreeUnicodeString(&unicodeString);
  269. }
  270. return status;
  271. }
  272. NTSTATUS
  273. PipQueryDeviceUniqueId (
  274. PDEVICE_INFORMATION DeviceInfo,
  275. PWCHAR *DeviceId
  276. )
  277. /*++
  278. Routine Description:
  279. This function returns the unique id for the particular device.
  280. Arguments:
  281. DeviceData - Device data information for the specificied device.
  282. DeviceId - supplies a pointer to a variable to receive device id.
  283. Return Value:
  284. NTSTATUS code.
  285. --*/
  286. {
  287. NTSTATUS status = STATUS_SUCCESS;
  288. //
  289. // Set up device's unique id.
  290. // device unique id = SerialNumber of the card
  291. //
  292. *DeviceId = (PWCHAR)ExAllocatePool (
  293. PagedPool,
  294. (8 + 1) * sizeof(WCHAR) // serial number + null
  295. );
  296. if (*DeviceId) {
  297. swprintf (*DeviceId,
  298. L"%08X",
  299. ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber
  300. );
  301. #if IDBG
  302. {
  303. ANSI_STRING ansiString;
  304. UNICODE_STRING unicodeString;
  305. RtlInitUnicodeString(&unicodeString, *DeviceId);
  306. RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
  307. DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer);
  308. RtlFreeAnsiString(&ansiString);
  309. }
  310. #endif
  311. } else {
  312. status = STATUS_INSUFFICIENT_RESOURCES;
  313. }
  314. return status;
  315. }
  316. NTSTATUS
  317. PipQueryDeviceId (
  318. PDEVICE_INFORMATION DeviceInfo,
  319. PWCHAR *DeviceId,
  320. ULONG IdIndex
  321. )
  322. /*++
  323. Routine Description:
  324. This function returns the device id for the particular device.
  325. Arguments:
  326. DeviceInfo - Device information for the specificied device.
  327. DeviceId - supplies a pointer to a variable to receive the device id.
  328. IdIndex - specifies device id or compatible id (0 - device id)
  329. Return Value:
  330. NTSTATUS code.
  331. --*/
  332. {
  333. NTSTATUS status = STATUS_SUCCESS;
  334. PWSTR format;
  335. ULONG size;
  336. UCHAR eisaId[8];
  337. UNICODE_STRING unicodeString;
  338. ANSI_STRING ansiString;
  339. //
  340. // Set up device's id.
  341. // device id = VenderId + Logical device number
  342. //
  343. if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) {
  344. format = L"ISAPNP\\%s";
  345. size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR);
  346. } else {
  347. format = L"ISAPNP\\%s_DEV%04X";
  348. size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR);
  349. }
  350. PipDecompressEisaId(
  351. ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId,
  352. eisaId
  353. );
  354. RtlInitAnsiString(&ansiString, eisaId);
  355. RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
  356. size += unicodeString.Length;
  357. *DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size);
  358. if (*DeviceId) {
  359. swprintf (*DeviceId,
  360. format,
  361. unicodeString.Buffer,
  362. DeviceInfo->LogicalDeviceNumber
  363. );
  364. #if IDBG
  365. {
  366. ANSI_STRING dbgAnsiString;
  367. UNICODE_STRING dbgUnicodeString;
  368. RtlInitUnicodeString(&dbgUnicodeString, *DeviceId);
  369. RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE);
  370. DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer);
  371. RtlFreeAnsiString(&dbgAnsiString);
  372. }
  373. #endif
  374. } else {
  375. status = STATUS_INSUFFICIENT_RESOURCES;
  376. }
  377. RtlFreeUnicodeString(&unicodeString);
  378. return status;
  379. }
  380. NTSTATUS
  381. PipQueryDeviceResources (
  382. PDEVICE_INFORMATION DeviceInfo,
  383. ULONG BusNumber,
  384. PCM_RESOURCE_LIST *CmResources,
  385. ULONG *Size
  386. )
  387. /*++
  388. Routine Description:
  389. This function returns the bus resources being used by the specified device
  390. Arguments:
  391. DeviceInfo - Device information for the specificied slot
  392. BusNumber - should always be 0
  393. CmResources - supplies a pointer to a variable to receive the device resource
  394. data.
  395. Size - Supplies a pointer to avariable to receive the size of device resource
  396. data.
  397. Return Value:
  398. NTSTATUS code.
  399. --*/
  400. {
  401. ULONG length;
  402. NTSTATUS status;
  403. PCM_RESOURCE_LIST cmResources;
  404. PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
  405. DeviceInfo->LogicalDeviceNumber,
  406. FALSE
  407. );
  408. status = PipReadDeviceBootResourceData (
  409. BusNumber,
  410. DeviceInfo->DeviceData,
  411. &cmResources,
  412. &length
  413. );
  414. //
  415. // Put all cards into wait for key state.
  416. //
  417. PipWriteAddress(CONFIG_CONTROL_PORT);
  418. PipWriteData(CONTROL_WAIT_FOR_KEY);
  419. //
  420. // Return results
  421. //
  422. if (NT_SUCCESS(status)) {
  423. if (length == 0) {
  424. cmResources = NULL; // Just to make sure.
  425. }
  426. *CmResources = cmResources;
  427. *Size = length;
  428. #if IDBG
  429. PipDumpCmResourceList(cmResources);
  430. #endif
  431. }
  432. return status;
  433. }
  434. NTSTATUS
  435. PipQueryDeviceResourceRequirements (
  436. PDEVICE_INFORMATION DeviceInfo,
  437. ULONG BusNumber,
  438. ULONG Slot,
  439. PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
  440. ULONG *Size
  441. )
  442. /*++
  443. Routine Description:
  444. This function returns the possible bus resources that this device may be
  445. satisfied with.
  446. Arguments:
  447. DeviceData - Device data information for the specificied slot
  448. BusNumber - Supplies the bus number
  449. Slot - supplies the slot number of the BusNumber
  450. IoResources - supplies a pointer to a variable to receive the IO resource
  451. requirements list
  452. Return Value:
  453. The device control is completed
  454. --*/
  455. {
  456. ULONG length = 0;
  457. NTSTATUS status;
  458. PUCHAR deviceData;
  459. PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
  460. deviceData = DeviceInfo->DeviceData;
  461. status = PbBiosResourcesToNtResources (
  462. BusNumber,
  463. Slot,
  464. &deviceData,
  465. &ioResources,
  466. &length
  467. );
  468. //
  469. // Return results
  470. //
  471. if (NT_SUCCESS(status)) {
  472. if (length == 0) {
  473. ioResources = NULL; // Just ot make sure
  474. }
  475. *IoResources = ioResources;
  476. *Size = length;
  477. #if IDBG
  478. PipDumpIoResourceList(ioResources);
  479. #endif
  480. }
  481. return status;
  482. }
  483. NTSTATUS
  484. PipSetDeviceResources (
  485. PDEVICE_INFORMATION DeviceInfo,
  486. PCM_RESOURCE_LIST CmResources
  487. )
  488. /*++
  489. Routine Description:
  490. This function configures the device to the specified device setttings
  491. Arguments:
  492. DeviceInfo - Device information for the specificied slot
  493. CmResources - pointer to the desired resource list
  494. Return Value:
  495. NTSTATUS code.
  496. --*/
  497. {
  498. NTSTATUS status;
  499. PAGED_CODE();
  500. PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
  501. DeviceInfo->LogicalDeviceNumber,
  502. FALSE
  503. );
  504. //
  505. // Set resource settings for the device
  506. //
  507. status = PipWriteDeviceBootResourceData (
  508. DeviceInfo->DeviceData,
  509. (PCM_RESOURCE_LIST) CmResources
  510. );
  511. //
  512. // Put all cards into wait for key state.
  513. //
  514. PipWriteAddress(CONFIG_CONTROL_PORT);
  515. PipWriteData(CONTROL_WAIT_FOR_KEY);
  516. return status;
  517. }