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.

2348 lines
66 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Registry support for the video port driver.
  7. Author:
  8. Andre Vachon (andreva) 01-Mar-1992
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "videoprt.h"
  15. //
  16. // Local routines.
  17. //
  18. BOOLEAN
  19. CheckIoEnabled(
  20. PVOID HwDeviceExtension,
  21. ULONG NumAccessRanges,
  22. PVIDEO_ACCESS_RANGE AccessRanges
  23. );
  24. ULONG
  25. GetCmResourceListSize(
  26. PCM_RESOURCE_LIST CmResourceList
  27. );
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE,VpGetFlags)
  30. #pragma alloc_text(PAGE,pOverrideConflict)
  31. #pragma alloc_text(PAGE,VideoPortGetAccessRanges)
  32. #pragma alloc_text(PAGE,pVideoPortReportResourceList)
  33. #pragma alloc_text(PAGE,VideoPortVerifyAccessRanges)
  34. #pragma alloc_text(PAGE,CheckIoEnabled)
  35. #pragma alloc_text(PAGE,VpReleaseResources)
  36. #pragma alloc_text(PAGE,VpIsResourceInList)
  37. #pragma alloc_text(PAGE,VpAppendToRequirementsList)
  38. #pragma alloc_text(PAGE,VpIsLegacyAccessRange)
  39. #pragma alloc_text(PAGE,GetCmResourceListSize)
  40. #pragma alloc_text(PAGE,VpRemoveFromResourceList)
  41. #pragma alloc_text(PAGE,VpTranslateResource)
  42. #pragma alloc_text(PAGE,VpIsVgaResource)
  43. #endif
  44. NTSTATUS
  45. VpGetFlags(
  46. PUNICODE_STRING RegistryPath,
  47. PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
  48. PULONG Flags
  49. )
  50. /*++
  51. Routine Description:
  52. Checks for the existance of the PnP key/value in the device's
  53. registry path.
  54. Return Value:
  55. TRUE if the flag exists, FALSE otherwise.
  56. --*/
  57. {
  58. PWSTR Path;
  59. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  60. ULONG pnpEnabled = 0;
  61. ULONG legacyDetect = 0;
  62. ULONG defaultValue = 0;
  63. ULONG bootDriver = 0;
  64. ULONG reportDevice = 0;
  65. PWSTR Table[] = {L"\\VgaSave", NULL};
  66. PWSTR SubStr, *Item = Table;
  67. ULONG Len;
  68. RTL_QUERY_REGISTRY_TABLE QueryTable[] = {
  69. {NULL, RTL_QUERY_REGISTRY_DIRECT, L"LegacyDetect",
  70. &legacyDetect, REG_DWORD, &defaultValue, 4},
  71. {NULL, RTL_QUERY_REGISTRY_DIRECT, L"BootDriver",
  72. &bootDriver, REG_DWORD, &defaultValue, 4},
  73. {NULL, RTL_QUERY_REGISTRY_DIRECT, L"ReportDevice",
  74. &reportDevice, REG_DWORD, &defaultValue, 4},
  75. {NULL, 0, NULL}
  76. };
  77. *Flags = 0;
  78. Path = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,
  79. RegistryPath->Length + sizeof(UNICODE_NULL),
  80. VP_TAG);
  81. if (Path)
  82. {
  83. RtlCopyMemory(Path,
  84. RegistryPath->Buffer,
  85. RegistryPath->Length);
  86. *(Path + (RegistryPath->Length / sizeof(UNICODE_NULL))) = UNICODE_NULL;
  87. pVideoDebugPrint((1, "PnP path: %ws\n", Path));
  88. RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  89. Path,
  90. &QueryTable[0],
  91. NULL,
  92. NULL);
  93. //
  94. // If the PnP Entry points are present, then we will treat this
  95. // driver as a PnP driver.
  96. //
  97. if ( (HwInitializationData->HwInitDataSize >=
  98. FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA, HwQueryInterface)) &&
  99. (HwInitializationData->HwSetPowerState != NULL) &&
  100. (HwInitializationData->HwGetPowerState != NULL) &&
  101. (HwInitializationData->HwGetVideoChildDescriptor != NULL) )
  102. {
  103. pVideoDebugPrint((1, "videoprt: The miniport is a PnP miniport."));
  104. pnpEnabled = TRUE;
  105. }
  106. //
  107. // REPORT_DEVICE is only valid if PNP_ENABLED is true.
  108. //
  109. // We don't want to report a device to the PnP system if
  110. // we don't have a PnP driver.
  111. //
  112. if (!pnpEnabled)
  113. {
  114. reportDevice = 0;
  115. }
  116. *Flags = (pnpEnabled ? PNP_ENABLED : 0) |
  117. (legacyDetect ? LEGACY_DETECT : 0) |
  118. (bootDriver ? BOOT_DRIVER : 0) |
  119. (reportDevice ? REPORT_DEVICE : 0);
  120. //
  121. // Free the memory we allocated above.
  122. //
  123. ExFreePool(Path);
  124. //
  125. // Determine if the current miniport is the VGA miniport.
  126. //
  127. while (*Item) {
  128. Len = wcslen(*Item);
  129. SubStr = RegistryPath->Buffer + (RegistryPath->Length / 2) - Len;
  130. if (!_wcsnicmp(SubStr, *Item, Len)) {
  131. pVideoDebugPrint((1, "This IS the vga miniport\n"));
  132. *Flags |= VGA_DRIVER;
  133. break;
  134. }
  135. Item++;
  136. }
  137. pVideoDebugPrint((1, "Flags = %d\n", *Flags));
  138. ntStatus = STATUS_SUCCESS;
  139. }
  140. return ntStatus;
  141. }
  142. BOOLEAN
  143. IsMirrorDriver(
  144. PFDO_EXTENSION fdoExtension
  145. )
  146. /*++
  147. Routine Description:
  148. Checks if the driver is a mirror onr or not.
  149. This function may be called ONLY after DriverRegistryPath was initialized.
  150. That is, after VideoPortFindAdapter2 or VideoPortCreateSecondaryDisplay
  151. were called.
  152. Return Value:
  153. TRUE if the driver is a mirror one, FALSE otherwise.
  154. --*/
  155. {
  156. ULONG MirrorDriver = 0;
  157. ASSERT ((fdoExtension != NULL) && IS_FDO(fdoExtension));
  158. VideoPortGetRegistryParameters(fdoExtension->HwDeviceExtension,
  159. L"MirrorDriver",
  160. FALSE,
  161. VpRegistryCallback,
  162. &MirrorDriver);
  163. return (MirrorDriver != 0);
  164. }
  165. BOOLEAN
  166. pOverrideConflict(
  167. PFDO_EXTENSION FdoExtension,
  168. BOOLEAN bSetResources
  169. )
  170. /*++
  171. Routine Description:
  172. Determine if the port driver should override the conflict in the registry.
  173. bSetResources determines if the routine is checking the state for setting
  174. the resources in the registry, or for cleaning them.
  175. For example, if we are running basevideo and there is a conflict with the
  176. vga, we want to override the conflict, but not clear the contents of
  177. the registry.
  178. Return Value:
  179. TRUE if it should, FALSE if it should not.
  180. --*/
  181. {
  182. if (FdoExtension->Flags & VGA_DRIVER) {
  183. return (bSetResources || (!VpBaseVideo));
  184. }
  185. return FALSE;
  186. }
  187. BOOLEAN
  188. CheckResourceList(
  189. ULONG BusNumber,
  190. ULONG Slot
  191. )
  192. /*++
  193. Routine Description:
  194. This routine remembers which bus numbers and slot numbers we've handed
  195. out resources for. This will prevent us from handing out resources
  196. to a legacy driver trying to control a device which a PnP driver
  197. is already controlling.
  198. Arguments:
  199. BusNumber - The bus number on which the device resides.
  200. Slot - The slot/function number of the device on the bus.
  201. Returns:
  202. TRUE if resources have already been handed out for the device,
  203. FALSE otherwise.
  204. --*/
  205. {
  206. PDEVICE_ADDRESS DeviceAddress;
  207. DeviceAddress = gDeviceAddressList;
  208. while (DeviceAddress) {
  209. if ((DeviceAddress->BusNumber == BusNumber) &&
  210. (DeviceAddress->Slot == Slot)) {
  211. return TRUE;
  212. }
  213. DeviceAddress = DeviceAddress->Next;
  214. }
  215. return FALSE;
  216. }
  217. VOID
  218. AddToResourceList(
  219. ULONG BusNumber,
  220. ULONG Slot
  221. )
  222. /*++
  223. Routine Description:
  224. This routine checks to see if resources have already been handed
  225. out for the device on the given bus/slot.
  226. Arguments:
  227. BusNumber - The bus number on which the device resides.
  228. Slot - The slot/function number of the device on the bus.
  229. Returns:
  230. none
  231. --*/
  232. {
  233. PDEVICE_ADDRESS DeviceAddress;
  234. DeviceAddress = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,
  235. sizeof(DEVICE_ADDRESS),
  236. VP_TAG);
  237. if (DeviceAddress) {
  238. DeviceAddress->BusNumber = BusNumber;
  239. DeviceAddress->Slot = Slot;
  240. DeviceAddress->Next = gDeviceAddressList;
  241. gDeviceAddressList = DeviceAddress;
  242. }
  243. }
  244. VIDEOPORT_API
  245. VP_STATUS
  246. VideoPortGetAccessRanges(
  247. PVOID HwDeviceExtension,
  248. ULONG NumRequestedResources,
  249. PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
  250. ULONG NumAccessRanges,
  251. PVIDEO_ACCESS_RANGE AccessRanges,
  252. PVOID VendorId,
  253. PVOID DeviceId,
  254. PULONG Slot
  255. )
  256. /*++
  257. Routine Description:
  258. Walk the appropriate bus to get device information.
  259. Search for the appropriate device ID.
  260. Appropriate resources will be returned and automatically stored in the
  261. resourcemap.
  262. Arguments:
  263. HwDeviceExtension - Points to the miniport driver's device extension.
  264. NumRequestedResources - Number of entries in the RequestedResources array.
  265. RequestedResources - Optional pointer to an array ofRequestedResources
  266. the miniport driver wants to access.
  267. NumAccessRanges - Maximum number of access ranges that can be returned
  268. by the function.
  269. AccessRanges - Array of access ranges that will be returned to the driver.
  270. VendorId - Pointer to the vendor ID. On PCI, this is a pointer to a 16 bit
  271. word.
  272. DeviceId - Pointer to the Device ID. On PCI, this is a pointer to a 16 bit
  273. word.
  274. Slot - Pointer to the starting slot number for this search.
  275. Return Value:
  276. ERROR_MORE_DATA if the AccessRange structure is not large enough for the
  277. PCI config info.
  278. ERROR_DEV_NOT_EXIST is the card is not found.
  279. NO_ERROR if the function succeded.
  280. --*/
  281. {
  282. PDEVICE_SPECIFIC_EXTENSION DoSpecificExtension;
  283. PFDO_EXTENSION fdoExtension;
  284. UNICODE_STRING unicodeString;
  285. ULONG i;
  286. ULONG j;
  287. PCM_RESOURCE_LIST cmResourceList;
  288. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
  289. VP_STATUS status;
  290. UCHAR bShare;
  291. PPCI_SLOT_NUMBER slotData = (PPCI_SLOT_NUMBER)Slot;
  292. DoSpecificExtension = GET_DSP_EXT(HwDeviceExtension);
  293. fdoExtension = DoSpecificExtension->pFdoExtension;
  294. // Hack Add extra R so the Device0 key does not get created as volatile
  295. // a mess up the subsequent driver install.
  296. *(LPWSTR) (((PUCHAR)DoSpecificExtension->DriverRegistryPath) +
  297. DoSpecificExtension->DriverRegistryPathLength) = L'R';
  298. RtlInitUnicodeString(&unicodeString, DoSpecificExtension->DriverRegistryPath);
  299. //
  300. // Assert drivers do set those parameters properly
  301. //
  302. #if DBG
  303. if ((NumRequestedResources == 0) != (RequestedResources == NULL)) {
  304. pVideoDebugPrint((0, "VideoPortGetDeviceResources: Parameters for requested resource are inconsistent\n"));
  305. }
  306. #endif
  307. //
  308. // An empty requested resource list means we want to automatic behavoir.
  309. // Just call the HAL to get all the information
  310. //
  311. if (NumRequestedResources == 0) {
  312. if ((fdoExtension->Flags & LEGACY_DRIVER) != LEGACY_DRIVER) {
  313. //
  314. // If a PnP driver is requesting resources, then return what the
  315. // system passed in to us.
  316. //
  317. cmResourceList = fdoExtension->AllocatedResources;
  318. //
  319. // Return the slot number to the device.
  320. //
  321. if (Slot) {
  322. *Slot = fdoExtension->SlotNumber;
  323. }
  324. if (cmResourceList) {
  325. #if DBG
  326. DumpResourceList(cmResourceList);
  327. #endif
  328. status = NO_ERROR;
  329. } else {
  330. //
  331. // The system should always pass us resources.
  332. //
  333. ASSERT(FALSE);
  334. status = ERROR_INVALID_PARAMETER;
  335. }
  336. } else {
  337. #if defined(NO_LEGACY_DRIVERS)
  338. pVideoDebugPrint((0, "VideoPortGetDeviceResources: Sorry, no legacy device support.\n"));
  339. status = ERROR_INVALID_PARAMETER;
  340. #else
  341. //
  342. // An empty requested resource list means we want to automatic behavoir.
  343. // Just call the HAL to get all the information
  344. //
  345. PCI_COMMON_CONFIG pciBuffer;
  346. PPCI_COMMON_CONFIG pciData;
  347. //
  348. //
  349. // typedef struct _PCI_SLOT_NUMBER {
  350. // union {
  351. // struct {
  352. // ULONG DeviceNumber:5;
  353. // ULONG FunctionNumber:3;
  354. // ULONG Reserved:24;
  355. // } bits;
  356. // ULONG AsULONG;
  357. // } u;
  358. // } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
  359. //
  360. pciData = (PPCI_COMMON_CONFIG)&pciBuffer;
  361. //
  362. // Only PCI is supported for automatic querying
  363. //
  364. if (fdoExtension->AdapterInterfaceType == PCIBus) {
  365. status = ERROR_DEV_NOT_EXIST;
  366. //
  367. // Look on each slot
  368. //
  369. do
  370. {
  371. //
  372. // Look at each function.
  373. //
  374. do
  375. {
  376. if (HalGetBusData(PCIConfiguration,
  377. fdoExtension->SystemIoBusNumber,
  378. slotData->u.AsULONG,
  379. pciData,
  380. PCI_COMMON_HDR_LENGTH) == 0) {
  381. //
  382. // Out of functions. Go to next PCI bus.
  383. //
  384. continue;
  385. }
  386. if (pciData->VendorID != *((PUSHORT)VendorId) ||
  387. pciData->DeviceID != *((PUSHORT)DeviceId)) {
  388. //
  389. // Not our PCI device. Try next device/function
  390. //
  391. continue;
  392. }
  393. //
  394. // Check to see if resources have already been
  395. // assigned for this bus/slot.
  396. //
  397. if (CheckResourceList(fdoExtension->SystemIoBusNumber,
  398. slotData->u.AsULONG) == FALSE)
  399. {
  400. if (NT_SUCCESS(HalAssignSlotResources(&unicodeString,
  401. &VideoClassName,
  402. fdoExtension->FunctionalDeviceObject->DriverObject,
  403. fdoExtension->FunctionalDeviceObject,
  404. PCIBus,
  405. fdoExtension->SystemIoBusNumber,
  406. slotData->u.AsULONG,
  407. &cmResourceList))) {
  408. status = NO_ERROR;
  409. AddToResourceList(fdoExtension->SystemIoBusNumber,
  410. slotData->u.AsULONG);
  411. break;
  412. } else {
  413. //
  414. // ToDo: Log this error.
  415. //
  416. status = ERROR_INVALID_PARAMETER;
  417. }
  418. } else {
  419. //
  420. // Resources already assigned for this device.
  421. //
  422. pVideoDebugPrint((0, "VIDEOPRT: Another driver is already "
  423. "controlling this device.\n"));
  424. ASSERT(FALSE);
  425. status = ERROR_DEV_NOT_EXIST;
  426. }
  427. } while (++slotData->u.bits.FunctionNumber != 0);
  428. //
  429. // break if we found the device already.
  430. //
  431. if (status != ERROR_DEV_NOT_EXIST) {
  432. break;
  433. }
  434. } while (++slotData->u.bits.DeviceNumber != 0);
  435. } else {
  436. //
  437. // This is not a supported bus type.
  438. //
  439. status = ERROR_INVALID_PARAMETER;
  440. }
  441. #endif // NO_LEGACY_DRIVERS
  442. }
  443. } else {
  444. PIO_RESOURCE_REQUIREMENTS_LIST requestedResources;
  445. ULONG requestedResourceSize;
  446. NTSTATUS ntStatus;
  447. status = NO_ERROR;
  448. //
  449. // The caller has specified some resources.
  450. // Lets call IoAssignResources with that and see what comes back.
  451. //
  452. requestedResourceSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
  453. ((NumRequestedResources - 1) *
  454. sizeof(IO_RESOURCE_DESCRIPTOR));
  455. requestedResources = ExAllocatePoolWithTag(PagedPool,
  456. requestedResourceSize,
  457. VP_TAG);
  458. if (requestedResources) {
  459. RtlZeroMemory(requestedResources, requestedResourceSize);
  460. requestedResources->ListSize = requestedResourceSize;
  461. requestedResources->InterfaceType = fdoExtension->AdapterInterfaceType;
  462. requestedResources->BusNumber = fdoExtension->SystemIoBusNumber;
  463. requestedResources->SlotNumber = slotData->u.bits.DeviceNumber;
  464. requestedResources->AlternativeLists = 1;
  465. requestedResources->List[0].Version = 1;
  466. requestedResources->List[0].Revision = 1;
  467. requestedResources->List[0].Count = NumRequestedResources;
  468. RtlMoveMemory(&(requestedResources->List[0].Descriptors[0]),
  469. RequestedResources,
  470. NumRequestedResources * sizeof(IO_RESOURCE_DESCRIPTOR));
  471. ntStatus = IoAssignResources(&unicodeString,
  472. &VideoClassName,
  473. fdoExtension->FunctionalDeviceObject->DriverObject,
  474. fdoExtension->FunctionalDeviceObject,
  475. requestedResources,
  476. &cmResourceList);
  477. ExFreePool(requestedResources);
  478. if (!NT_SUCCESS(ntStatus)) {
  479. status = ERROR_INVALID_PARAMETER;
  480. }
  481. } else {
  482. status = ERROR_NOT_ENOUGH_MEMORY;
  483. }
  484. }
  485. if (status == NO_ERROR) {
  486. VIDEO_ACCESS_RANGE TempRange;
  487. //
  488. // We now have a valid cmResourceList.
  489. // Lets translate it back to access ranges so the driver
  490. // only has to deal with one type of list.
  491. //
  492. //
  493. // NOTE: The resources have already been reported at this point in
  494. // time.
  495. //
  496. //
  497. // Walk resource list to update configuration information.
  498. //
  499. for (i = 0, j = 0;
  500. (i < cmResourceList->List->PartialResourceList.Count) &&
  501. (status == NO_ERROR);
  502. i++) {
  503. //
  504. // Get resource descriptor.
  505. //
  506. cmResourceDescriptor =
  507. &cmResourceList->List->PartialResourceList.PartialDescriptors[i];
  508. //
  509. // Get the share disposition
  510. //
  511. if (cmResourceDescriptor->ShareDisposition == CmResourceShareShared) {
  512. bShare = 1;
  513. } else {
  514. bShare = 0;
  515. }
  516. switch (cmResourceDescriptor->Type) {
  517. case CmResourceTypePort:
  518. case CmResourceTypeMemory:
  519. //
  520. // common part
  521. //
  522. TempRange.RangeLength =
  523. cmResourceDescriptor->u.Memory.Length;
  524. TempRange.RangeStart =
  525. cmResourceDescriptor->u.Memory.Start;
  526. TempRange.RangeVisible = 0;
  527. TempRange.RangeShareable = bShare;
  528. TempRange.RangePassive = 0;
  529. //
  530. // separate part
  531. //
  532. if (cmResourceDescriptor->Type == CmResourceTypePort) {
  533. TempRange.RangeInIoSpace = 1;
  534. } else {
  535. TempRange.RangeInIoSpace = 0;
  536. }
  537. //
  538. // See if we need to return the resource to the driver.
  539. //
  540. if (!VpIsLegacyAccessRange(fdoExtension, &TempRange)) {
  541. if (j == NumAccessRanges) {
  542. status = ERROR_MORE_DATA;
  543. break;
  544. } else {
  545. //
  546. // Only modify the AccessRange array if we are writing
  547. // valid data.
  548. //
  549. AccessRanges[j] = TempRange;
  550. j++;
  551. }
  552. }
  553. break;
  554. case CmResourceTypeInterrupt:
  555. fdoExtension->MiniportConfigInfo->BusInterruptVector =
  556. cmResourceDescriptor->u.Interrupt.Vector;
  557. fdoExtension->MiniportConfigInfo->BusInterruptLevel =
  558. cmResourceDescriptor->u.Interrupt.Level;
  559. fdoExtension->MiniportConfigInfo->InterruptShareable =
  560. bShare;
  561. break;
  562. case CmResourceTypeDma:
  563. fdoExtension->MiniportConfigInfo->DmaChannel =
  564. cmResourceDescriptor->u.Dma.Channel;
  565. fdoExtension->MiniportConfigInfo->DmaPort =
  566. cmResourceDescriptor->u.Dma.Port;
  567. fdoExtension->MiniportConfigInfo->DmaShareable =
  568. bShare;
  569. break;
  570. default:
  571. pVideoDebugPrint((1, "VideoPortGetAccessRanges: Unknown descriptor type %x\n",
  572. cmResourceDescriptor->Type ));
  573. break;
  574. }
  575. }
  576. if (fdoExtension->Flags & LEGACY_DRIVER) {
  577. //
  578. // Free the resource provided by the IO system.
  579. //
  580. ExFreePool(cmResourceList);
  581. }
  582. }
  583. // Hack remove extra R
  584. *(LPWSTR) (((PUCHAR)DoSpecificExtension->DriverRegistryPath) +
  585. DoSpecificExtension->DriverRegistryPathLength) = UNICODE_NULL;
  586. return status;
  587. } // VideoPortGetDeviceResources()
  588. BOOLEAN
  589. VpIsVgaResource(
  590. PVIDEO_ACCESS_RANGE AccessRange
  591. )
  592. /*++
  593. Routine Description:
  594. Indicates whether the given access range is a vga access range.
  595. Arguments:
  596. AccessRange - The access range to examine.
  597. Returns:
  598. TRUE if it is a VGA access range,
  599. FALSE otherwise.
  600. Notes:
  601. This routine does not take into account the length of the access range.
  602. --*/
  603. {
  604. if (AccessRange->RangeInIoSpace) {
  605. ULONGLONG Port = AccessRange->RangeStart.QuadPart;
  606. if (((Port >= 0x3b0) && (Port <= 0x3bb)) ||
  607. ((Port >= 0x3c0) && (Port <= 0x3df))) {
  608. return TRUE;
  609. }
  610. } else {
  611. if (AccessRange->RangeStart.QuadPart == 0xa0000) {
  612. return TRUE;
  613. }
  614. }
  615. return FALSE;
  616. }
  617. BOOLEAN
  618. VpTranslateResource(
  619. IN PFDO_EXTENSION fdoExtension,
  620. IN OUT PULONG InIoSpace,
  621. IN PPHYSICAL_ADDRESS PhysicalAddress,
  622. OUT PPHYSICAL_ADDRESS TranslatedAddress
  623. )
  624. /*++
  625. Routine Description:
  626. This routine ensures that we do not report any PnP assigned
  627. resources back to the system.
  628. Arguments:
  629. fdoExtension - The device extension for the device.
  630. PhysicalAddress - The physical address that needs to be translated
  631. TranslatedAddress - The location in which to store the translated address.
  632. Return Value:
  633. TRUE if the resource was translated
  634. FALSE otherwise.
  635. --*/
  636. {
  637. PCM_FULL_RESOURCE_DESCRIPTOR pcmFullRaw;
  638. PCM_PARTIAL_RESOURCE_LIST pcmPartialRaw;
  639. PCM_PARTIAL_RESOURCE_DESCRIPTOR pcmDescriptRaw;
  640. PCM_FULL_RESOURCE_DESCRIPTOR pcmFullTranslated;
  641. PCM_PARTIAL_RESOURCE_LIST pcmPartialTranslated;
  642. PCM_PARTIAL_RESOURCE_DESCRIPTOR pcmDescriptTranslated;
  643. ULONG i, j;
  644. BOOLEAN IoAddress = (BOOLEAN)(*InIoSpace & VIDEO_MEMORY_SPACE_IO);
  645. //
  646. // In the case of the non-pnp vga driver we might not have had resources list
  647. // given to us, so we can't translate the physical address. In that case
  648. // we'll be relying on the Hal to do the translation for us.
  649. //
  650. if (fdoExtension->RawResources == NULL) {
  651. return FALSE;
  652. }
  653. pcmFullRaw = fdoExtension->RawResources->List;
  654. pcmFullTranslated = fdoExtension->TranslatedResources->List;
  655. for (i = 0; i < fdoExtension->RawResources->Count; i++) {
  656. pcmPartialRaw = &(pcmFullRaw->PartialResourceList);
  657. pcmDescriptRaw = pcmPartialRaw->PartialDescriptors;
  658. pcmPartialTranslated = &(pcmFullTranslated->PartialResourceList);
  659. pcmDescriptTranslated = pcmPartialTranslated->PartialDescriptors;
  660. for (j = 0; j < pcmPartialRaw->Count; j++) {
  661. if ((pcmDescriptRaw->Type == CmResourceTypeMemory) &&
  662. (pcmDescriptRaw->u.Memory.Start.QuadPart == PhysicalAddress->QuadPart) &&
  663. (IoAddress == FALSE)) {
  664. *TranslatedAddress =
  665. pcmDescriptTranslated->u.Memory.Start;
  666. if ((pcmDescriptTranslated->Type == CmResourceTypePort) &&
  667. ((*InIoSpace & 0x4) == 0))
  668. {
  669. *InIoSpace = VIDEO_MEMORY_SPACE_IO;
  670. } else {
  671. *InIoSpace = 0;
  672. }
  673. return TRUE;
  674. }
  675. if ((pcmDescriptRaw->Type == CmResourceTypePort) &&
  676. (pcmDescriptRaw->u.Port.Start.QuadPart == PhysicalAddress->QuadPart) &&
  677. (IoAddress == TRUE)) {
  678. *TranslatedAddress =
  679. pcmDescriptTranslated->u.Port.Start;
  680. if ((pcmDescriptTranslated->Type == CmResourceTypePort) &&
  681. ((*InIoSpace & 0x4) == 0))
  682. {
  683. *InIoSpace = VIDEO_MEMORY_SPACE_IO;
  684. } else {
  685. *InIoSpace = 0;
  686. }
  687. return TRUE;
  688. }
  689. pcmDescriptRaw++;
  690. pcmDescriptTranslated++;
  691. }
  692. pcmFullRaw = (PCM_FULL_RESOURCE_DESCRIPTOR) pcmDescriptRaw;
  693. pcmFullTranslated = (PCM_FULL_RESOURCE_DESCRIPTOR) pcmDescriptTranslated;
  694. }
  695. return FALSE;
  696. }
  697. BOOLEAN
  698. VpIsResourceInList(
  699. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource,
  700. PCM_FULL_RESOURCE_DESCRIPTOR pFullResource,
  701. PCM_RESOURCE_LIST removeList
  702. )
  703. /*++
  704. Routine Description:
  705. This routine ensures that we do not report any PnP assigned
  706. resources back to the system.
  707. Arguments:
  708. pResource - The resource which we are looking for in the removeList.
  709. pFullResource - contains bus info about pResource.
  710. removeList - Any resources in this list which appear in the
  711. resourceList will be removed from the resourceList.
  712. Return Value:
  713. TRUE if the resource is in the list,
  714. FALSE otherwise.
  715. --*/
  716. {
  717. PCM_FULL_RESOURCE_DESCRIPTOR pcmFull;
  718. PCM_PARTIAL_RESOURCE_LIST pcmPartial;
  719. PCM_PARTIAL_RESOURCE_DESCRIPTOR pcmDescript;
  720. ULONG i, j;
  721. if (!removeList) {
  722. //
  723. // If we have not list of resources to remove, then
  724. // simply return.
  725. //
  726. return FALSE;
  727. }
  728. pcmFull = &(removeList->List[0]);
  729. for (i=0; i<removeList->Count; i++)
  730. {
  731. pcmPartial = &(pcmFull->PartialResourceList);
  732. pcmDescript = &(pcmPartial->PartialDescriptors[0]);
  733. for (j=0; j<pcmPartial->Count; j++)
  734. {
  735. if (pcmDescript->Type == pResource->Type) {
  736. switch(pcmDescript->Type) {
  737. case CmResourceTypeMemory:
  738. case CmResourceTypePort:
  739. if ((pResource->u.Memory.Start.LowPart >= pcmDescript->u.Memory.Start.LowPart) &&
  740. ((pResource->u.Memory.Start.LowPart + pResource->u.Memory.Length) <=
  741. (pcmDescript->u.Memory.Start.LowPart + pcmDescript->u.Memory.Length))) {
  742. //
  743. // The resources passed in match one of the resources
  744. // in the list.
  745. //
  746. return TRUE;
  747. }
  748. break;
  749. case CmResourceTypeInterrupt:
  750. //
  751. // We don't want to report interrupts on the FDO.
  752. //
  753. return TRUE;
  754. default:
  755. if (!memcmp(&pcmDescript->u, &pResource->u, sizeof(pResource->u))) {
  756. //
  757. // The resources passed in match one of the resources
  758. // in the list.
  759. //
  760. return TRUE;
  761. }
  762. }
  763. }
  764. pcmDescript++;
  765. }
  766. pcmFull = (PCM_FULL_RESOURCE_DESCRIPTOR) pcmDescript;
  767. }
  768. return FALSE;
  769. }
  770. VOID
  771. VpReleaseResources(
  772. PFDO_EXTENSION FdoExtension
  773. )
  774. /*++
  775. Routine Description:
  776. This routine will release all resource claims for a given device object.
  777. Arguments:
  778. DeviceObject - The device object for which to release resource claims.
  779. --*/
  780. {
  781. PDEVICE_OBJECT DeviceObject = FdoExtension->FunctionalDeviceObject;
  782. ULONG_PTR emptyResourceList = 0;
  783. BOOLEAN ignore;
  784. pVideoDebugPrint((1, "videoprt: VpReleaseResources called.\n"));
  785. if (FdoExtension->Flags & (LEGACY_DETECT | VGA_DETECT)) {
  786. pVideoDebugPrint((2, "VideoPrt: VpReleaseResources LEGACY_DETECT\n"));
  787. IoReportResourceForDetection(FdoExtension->FunctionalDeviceObject->DriverObject,
  788. NULL,
  789. 0L,
  790. DeviceObject,
  791. (PCM_RESOURCE_LIST)&emptyResourceList,
  792. sizeof (ULONG),
  793. &ignore);
  794. } else {
  795. pVideoDebugPrint((2, "VideoPrt: VpReleaseResources non-LEGACY_DETECT\n"));
  796. IoReportResourceUsage(&VideoClassName,
  797. FdoExtension->FunctionalDeviceObject->DriverObject,
  798. NULL,
  799. 0L,
  800. DeviceObject,
  801. (PCM_RESOURCE_LIST)&emptyResourceList,
  802. sizeof(ULONG),
  803. FALSE,
  804. &ignore);
  805. }
  806. }
  807. NTSTATUS
  808. VpAppendToRequirementsList(
  809. IN PDEVICE_OBJECT DeviceObject,
  810. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementList,
  811. IN ULONG NumAccessRanges,
  812. IN PVIDEO_ACCESS_RANGE AccessRanges
  813. )
  814. /*++
  815. Routine Description:
  816. Builds a IoResourceRequirementsList for a given set of access ranges.
  817. Arguments:
  818. ResourceList - Pointer to location of the requirments list. Modified
  819. on completion to point to a new requirements list.
  820. NumAccessRanges - Number of access ranges in list.
  821. AccessRanges - List of resources.
  822. Returns:
  823. STATUS_SUCCESS if successful, otherwise a status code.
  824. Notes:
  825. This function free's the memory used by the original resource list,
  826. and allocates a new buffer for the appended resources list.
  827. --*/
  828. {
  829. PIO_RESOURCE_REQUIREMENTS_LIST OriginalRequirementList = *RequirementList;
  830. PIO_RESOURCE_DESCRIPTOR pioDescript;
  831. ULONG RequirementListSize;
  832. ULONG OriginalListSize;
  833. ULONG RequirementCount;
  834. ULONG i;
  835. RequirementCount = OriginalRequirementList->List[0].Count;
  836. OriginalListSize = OriginalRequirementList->ListSize;
  837. RequirementListSize = OriginalListSize +
  838. NumAccessRanges * sizeof(IO_RESOURCE_DESCRIPTOR);
  839. *RequirementList =
  840. (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePoolWithTag(PagedPool,
  841. RequirementListSize,
  842. VP_TAG);
  843. //
  844. // Return NULL if the structure could not be allocated.
  845. // Otherwise, fill it out.
  846. //
  847. if (*RequirementList == NULL) {
  848. *RequirementList = OriginalRequirementList;
  849. return STATUS_INSUFFICIENT_RESOURCES;
  850. } else {
  851. //
  852. // Copy the original resource list into the new one.
  853. //
  854. memcpy(*RequirementList, OriginalRequirementList, OriginalListSize);
  855. //
  856. // Free the original list
  857. //
  858. ExFreePool(OriginalRequirementList);
  859. //
  860. // Point to first free entry in requirements list
  861. //
  862. pioDescript =
  863. &((*RequirementList)->List[0].Descriptors[(*RequirementList)->List[0].Count]);
  864. //
  865. // For each entry in the access range, fill in an entry in the
  866. // resource list
  867. //
  868. for (i = 0; i < NumAccessRanges; i++) {
  869. //
  870. // We will never claim 0xC0000.
  871. //
  872. if ((AccessRanges->RangeStart.LowPart == 0xC0000) &&
  873. (AccessRanges->RangeInIoSpace == FALSE))
  874. {
  875. AccessRanges++;
  876. continue;
  877. }
  878. if (AccessRanges->RangeLength == 0) {
  879. AccessRanges++;
  880. continue;
  881. }
  882. //
  883. // Watch to see if the VGA resources get added to the
  884. // requirements list. If so set a flag so that we know
  885. // we don't need to reclaim VGA resources in FindAdapter.
  886. //
  887. if (VpIsVgaResource(AccessRanges)) {
  888. DeviceOwningVga = DeviceObject;
  889. }
  890. if (AccessRanges->RangeInIoSpace) {
  891. pioDescript->Type = CmResourceTypePort;
  892. pioDescript->Flags = CM_RESOURCE_PORT_IO;
  893. //
  894. // Disable 10_BIT_DECODE. This is causing problems for the
  895. // PnP folks. If someone has bad hardware, we'll just
  896. // require them to report all the passive port explicitly.
  897. //
  898. //if (VpIsVgaResource(AccessRanges)) {
  899. //
  900. // pioDescript->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  901. //}
  902. } else {
  903. pioDescript->Type = CmResourceTypeMemory;
  904. pioDescript->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  905. }
  906. if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE) {
  907. pioDescript->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
  908. }
  909. if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE) {
  910. pioDescript->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  911. }
  912. pioDescript->ShareDisposition =
  913. (AccessRanges->RangeShareable ?
  914. CmResourceShareShared :
  915. CmResourceShareDeviceExclusive);
  916. pioDescript->Option = IO_RESOURCE_PREFERRED;
  917. pioDescript->u.Memory.MinimumAddress = AccessRanges->RangeStart;
  918. pioDescript->u.Memory.MaximumAddress.QuadPart =
  919. AccessRanges->RangeStart.QuadPart +
  920. AccessRanges->RangeLength - 1;
  921. pioDescript->u.Memory.Alignment = 1;
  922. pioDescript->u.Memory.Length = AccessRanges->RangeLength;
  923. pioDescript++;
  924. AccessRanges++;
  925. RequirementCount++;
  926. }
  927. //
  928. // Update number of elements in list.
  929. //
  930. (*RequirementList)->List[0].Count = RequirementCount;
  931. (*RequirementList)->ListSize = RequirementListSize;
  932. }
  933. return STATUS_SUCCESS;
  934. }
  935. NTSTATUS
  936. pVideoPortReportResourceList(
  937. PDEVICE_SPECIFIC_EXTENSION DoSpecificExtension,
  938. ULONG NumAccessRanges,
  939. PVIDEO_ACCESS_RANGE AccessRanges,
  940. PBOOLEAN Conflict,
  941. PDEVICE_OBJECT DeviceObject,
  942. BOOLEAN ClaimUnlistedResources
  943. )
  944. /*++
  945. Routine Description:
  946. Creates a resource list which is used to query or report resource usage
  947. in the system
  948. Arguments:
  949. DriverObject - Pointer to the miniport's driver device extension.
  950. NumAccessRanges - Num of access ranges in the AccessRanges array.
  951. AccessRanges - Pointer to an array of access ranges used by a miniport
  952. driver.
  953. Conflict - Determines whether or not a conflict occured.
  954. DeviceObject - The device object to use when calling
  955. IoReportResourceUsage.
  956. ClaimUnlistedResources - If this flag is true, then the routine will
  957. also claim resources such as interrupts and DMA channels.
  958. Return Value:
  959. Returns the final status of the operation
  960. --*/
  961. {
  962. PFDO_EXTENSION FdoExtension = DoSpecificExtension->pFdoExtension;
  963. PCM_RESOURCE_LIST resourceList;
  964. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceDescriptor;
  965. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDescriptor;
  966. ULONG listLength = 0;
  967. ULONG size;
  968. ULONG i;
  969. ULONG Flags;
  970. NTSTATUS ntStatus;
  971. BOOLEAN overrideConflict;
  972. #if DBG
  973. PVIDEO_ACCESS_RANGE SaveAccessRanges=AccessRanges;
  974. #endif
  975. //
  976. // Create a resource list based on the information in the access range.
  977. // and the miniport config info.
  978. //
  979. listLength = NumAccessRanges;
  980. //
  981. // Determine if we have DMA and interrupt resources to report
  982. //
  983. if (FdoExtension->HwInterrupt &&
  984. ((FdoExtension->MiniportConfigInfo->BusInterruptLevel != 0) ||
  985. (FdoExtension->MiniportConfigInfo->BusInterruptVector != 0)) ) {
  986. listLength++;
  987. }
  988. if ((FdoExtension->MiniportConfigInfo->DmaChannel) &&
  989. (FdoExtension->MiniportConfigInfo->DmaPort)) {
  990. listLength++;
  991. }
  992. //
  993. // Allocate upper bound.
  994. //
  995. resourceList = (PCM_RESOURCE_LIST)
  996. ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,
  997. sizeof(CM_RESOURCE_LIST) * 2 +
  998. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * listLength,
  999. VP_TAG);
  1000. //
  1001. // Return NULL if the structure could not be allocated.
  1002. // Otherwise, fill it out.
  1003. //
  1004. if (!resourceList) {
  1005. return STATUS_INSUFFICIENT_RESOURCES;
  1006. } else {
  1007. size = sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1008. resourceList->Count = 1;
  1009. fullResourceDescriptor = &(resourceList->List[0]);
  1010. fullResourceDescriptor->InterfaceType = FdoExtension->AdapterInterfaceType;
  1011. fullResourceDescriptor->BusNumber = FdoExtension->SystemIoBusNumber;
  1012. fullResourceDescriptor->PartialResourceList.Version = 0;
  1013. fullResourceDescriptor->PartialResourceList.Revision = 0;
  1014. fullResourceDescriptor->PartialResourceList.Count = 0;
  1015. //
  1016. // For each entry in the access range, fill in an entry in the
  1017. // resource list
  1018. //
  1019. partialResourceDescriptor =
  1020. &(fullResourceDescriptor->PartialResourceList.PartialDescriptors[0]);
  1021. for (i = 0; i < NumAccessRanges; i++, AccessRanges++) {
  1022. //
  1023. // If someone tries to claim a range of length 0 skip it.
  1024. //
  1025. if (AccessRanges->RangeLength == 0) {
  1026. continue;
  1027. }
  1028. if (AccessRanges->RangeInIoSpace) {
  1029. //
  1030. // Fix up odd Matrox legacy resources.
  1031. //
  1032. if ((AccessRanges->RangeStart.QuadPart == 0xCF8) &&
  1033. !(FdoExtension->Flags & PNP_ENABLED)) {
  1034. continue;
  1035. }
  1036. partialResourceDescriptor->Type = CmResourceTypePort;
  1037. partialResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
  1038. //
  1039. // Check to see if the range should be marked as passive
  1040. // decode.
  1041. //
  1042. if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE) {
  1043. partialResourceDescriptor->Flags |=
  1044. CM_RESOURCE_PORT_PASSIVE_DECODE;
  1045. }
  1046. if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE) {
  1047. partialResourceDescriptor->Flags |=
  1048. CM_RESOURCE_PORT_10_BIT_DECODE;
  1049. }
  1050. //
  1051. // If this is a 0x2E8 port with bit 14 on, and it is
  1052. // not 0xE2E8 then mark the port as passive decode.
  1053. //
  1054. if (((AccessRanges->RangeStart.QuadPart & 0x43FE) == 0x42E8) &&
  1055. ((AccessRanges->RangeStart.QuadPart & 0xFFFC) != 0xE2E8)) {
  1056. pVideoDebugPrint((2, "Marking IO Port 0x%x as Passive Decode.\n",
  1057. AccessRanges->RangeStart.LowPart));
  1058. partialResourceDescriptor->Flags |=
  1059. CM_RESOURCE_PORT_PASSIVE_DECODE;
  1060. }
  1061. //
  1062. // ET4000 tries to claim this port but never touches it!
  1063. //
  1064. if ((AccessRanges->RangeStart.QuadPart & 0x217a) == 0x217a) {
  1065. pVideoDebugPrint((2, "Marking IO Port 0x%x as Passive Decode.\n",
  1066. AccessRanges->RangeStart.LowPart));
  1067. partialResourceDescriptor->Flags |=
  1068. CM_RESOURCE_PORT_PASSIVE_DECODE;
  1069. }
  1070. //
  1071. // If it is a VGA access range, mark it as 10-bit decode.
  1072. //
  1073. //
  1074. // Disable 10_BIT_DECODE. This is causing problems for the
  1075. // PnP folks. If someone has bad hardware, we'll just
  1076. // require them to report all the passive port explicitly.
  1077. //
  1078. //if (VpIsVgaResource(AccessRanges)) {
  1079. //
  1080. // partialResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
  1081. //}
  1082. } else {
  1083. //
  1084. // Fix up odd memory resources to let legacy Trident boot.
  1085. //
  1086. if (AccessRanges->RangeStart.LowPart == 0x70) {
  1087. continue;
  1088. }
  1089. //
  1090. // The device doesn't actually decode 0xC0000 so we
  1091. // shouldn't report it as a resource.
  1092. //
  1093. if (AccessRanges->RangeStart.LowPart == 0xC0000) {
  1094. continue;
  1095. }
  1096. partialResourceDescriptor->Type = CmResourceTypeMemory;
  1097. partialResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  1098. }
  1099. partialResourceDescriptor->ShareDisposition =
  1100. (AccessRanges->RangeShareable ?
  1101. CmResourceShareShared :
  1102. CmResourceShareDeviceExclusive);
  1103. partialResourceDescriptor->u.Memory.Start =
  1104. AccessRanges->RangeStart;
  1105. partialResourceDescriptor->u.Memory.Length =
  1106. AccessRanges->RangeLength;
  1107. //
  1108. // Increment the size for the new entry
  1109. //
  1110. if (!VpIsResourceInList(partialResourceDescriptor,
  1111. fullResourceDescriptor,
  1112. FdoExtension->RawResources))
  1113. {
  1114. //
  1115. // Only include this resource if it is not in the
  1116. // list of PnP allocated resources.
  1117. //
  1118. size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1119. fullResourceDescriptor->PartialResourceList.Count += 1;
  1120. partialResourceDescriptor++;
  1121. }
  1122. }
  1123. if (ClaimUnlistedResources) {
  1124. //
  1125. // Fill in the entry for the interrupt if it was present.
  1126. //
  1127. if (FdoExtension->HwInterrupt &&
  1128. ((FdoExtension->MiniportConfigInfo->BusInterruptLevel != 0) ||
  1129. (FdoExtension->MiniportConfigInfo->BusInterruptVector != 0)) ) {
  1130. partialResourceDescriptor->Type = CmResourceTypeInterrupt;
  1131. partialResourceDescriptor->ShareDisposition =
  1132. (FdoExtension->MiniportConfigInfo->InterruptShareable ?
  1133. CmResourceShareShared :
  1134. CmResourceShareDeviceExclusive);
  1135. partialResourceDescriptor->Flags = 0;
  1136. partialResourceDescriptor->u.Interrupt.Level =
  1137. FdoExtension->MiniportConfigInfo->BusInterruptLevel;
  1138. partialResourceDescriptor->u.Interrupt.Vector =
  1139. FdoExtension->MiniportConfigInfo->BusInterruptVector;
  1140. partialResourceDescriptor->u.Interrupt.Affinity = 0;
  1141. //
  1142. // Increment the size for the new entry
  1143. //
  1144. if (!VpIsResourceInList(partialResourceDescriptor,
  1145. fullResourceDescriptor,
  1146. FdoExtension->RawResources))
  1147. {
  1148. //
  1149. // Only include this resource if it is not in the
  1150. // list of PnP allocated resources.
  1151. //
  1152. size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1153. fullResourceDescriptor->PartialResourceList.Count += 1;
  1154. partialResourceDescriptor++;
  1155. } else {
  1156. pVideoDebugPrint((1, "pVideoPortReportResourceList: "
  1157. "Not reporting PnP assigned resource.\n"));
  1158. }
  1159. }
  1160. //
  1161. // Fill in the entry for the DMA channel.
  1162. //
  1163. if ((FdoExtension->MiniportConfigInfo->DmaChannel) &&
  1164. (FdoExtension->MiniportConfigInfo->DmaPort)) {
  1165. partialResourceDescriptor->Type = CmResourceTypeDma;
  1166. partialResourceDescriptor->ShareDisposition =
  1167. (FdoExtension->MiniportConfigInfo->DmaShareable ?
  1168. CmResourceShareShared :
  1169. CmResourceShareDeviceExclusive);
  1170. partialResourceDescriptor->Flags = 0;
  1171. partialResourceDescriptor->u.Dma.Channel =
  1172. FdoExtension->MiniportConfigInfo->DmaChannel;
  1173. partialResourceDescriptor->u.Dma.Port =
  1174. FdoExtension->MiniportConfigInfo->DmaPort;
  1175. partialResourceDescriptor->u.Dma.Reserved1 = 0;
  1176. //
  1177. // Increment the size for the new entry
  1178. //
  1179. if (!VpIsResourceInList(partialResourceDescriptor,
  1180. fullResourceDescriptor,
  1181. FdoExtension->RawResources))
  1182. {
  1183. //
  1184. // Only include this resource if it is not in the
  1185. // list of PnP allocated resources.
  1186. //
  1187. size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1188. fullResourceDescriptor->PartialResourceList.Count += 1;
  1189. partialResourceDescriptor++;
  1190. } else {
  1191. pVideoDebugPrint((1, "pVideoPortReportResourceList: "
  1192. "Not reporting PnP assigned resource.\n"));
  1193. }
  1194. }
  1195. }
  1196. //
  1197. // Determine if the conflict should be overriden.
  1198. //
  1199. //
  1200. // If we are loading the VGA, do not generate an error if it conflicts
  1201. // with another driver.
  1202. //
  1203. overrideConflict = pOverrideConflict(FdoExtension, TRUE);
  1204. #if DBG
  1205. if (overrideConflict) {
  1206. pVideoDebugPrint((2, "We are checking the vga driver resources\n"));
  1207. } else {
  1208. pVideoDebugPrint((2, "We are NOT checking vga driver resources\n"));
  1209. }
  1210. #endif
  1211. //
  1212. // Report resources.
  1213. //
  1214. Flags = FdoExtension->Flags;
  1215. if (Flags & (LEGACY_DETECT | VGA_DETECT)) {
  1216. ntStatus = IoReportResourceForDetection(FdoExtension->FunctionalDeviceObject->DriverObject,
  1217. NULL,
  1218. 0L,
  1219. DeviceObject,
  1220. resourceList,
  1221. size,
  1222. Conflict);
  1223. if ((NT_SUCCESS(ntStatus) == FALSE) && (Flags & VGA_DETECT)) {
  1224. //
  1225. // There are a few occacations where reporting resources
  1226. // for detection can fail when just calling IoReportResources
  1227. // would have succeeded. So, lets remove the VGA_DETECT
  1228. // flag and try detecting resources again below.
  1229. //
  1230. Flags &= ~VGA_DETECT;
  1231. }
  1232. }
  1233. if ((Flags & (LEGACY_DETECT | VGA_DETECT)) == 0) {
  1234. ntStatus = IoReportResourceUsage(&VideoClassName,
  1235. FdoExtension->FunctionalDeviceObject->DriverObject,
  1236. NULL,
  1237. 0L,
  1238. DeviceObject,
  1239. resourceList,
  1240. size,
  1241. overrideConflict,
  1242. Conflict);
  1243. if (NT_SUCCESS(ntStatus)) {
  1244. //
  1245. // Make sure the Flags reflect the way we acquired
  1246. // resources.
  1247. //
  1248. FdoExtension->Flags = Flags;
  1249. pVideoDebugPrint((1, "Videoprt: Legacy resources claimed. "
  1250. "Power management may be disabled.\n"));
  1251. }
  1252. }
  1253. #if DBG
  1254. if (!NT_SUCCESS(ntStatus)) {
  1255. //
  1256. // We failed to get the resources we required. Dump
  1257. // the requested resources into the registry.
  1258. //
  1259. PUSHORT ValueData;
  1260. ULONG ValueLength;
  1261. PULONG pulData;
  1262. PWCHAR p;
  1263. ULONG DbgListLength;
  1264. pVideoDebugPrint((1, "IoReportResourceList Failed:\n"));
  1265. for(DbgListLength = 0; DbgListLength < NumAccessRanges; ++DbgListLength) {
  1266. pVideoDebugPrint((1, "Address: %08x Length: %08x I/O: %-5s Visible: %-5s Shared: %-5s\n",
  1267. SaveAccessRanges[DbgListLength].RangeStart.LowPart,
  1268. SaveAccessRanges[DbgListLength].RangeLength,
  1269. SaveAccessRanges[DbgListLength].RangeInIoSpace ? "TRUE" : "FALSE",
  1270. SaveAccessRanges[DbgListLength].RangeVisible ? "TRUE" : "FALSE",
  1271. SaveAccessRanges[DbgListLength].RangeShareable ? "TRUE" : "FALSE"));
  1272. }
  1273. ValueLength = NumAccessRanges *
  1274. (sizeof(VIDEO_ACCESS_RANGE) * 2 + 4) *
  1275. sizeof(USHORT) +
  1276. sizeof(USHORT); // second NULL terminator for
  1277. // multi_sz
  1278. ValueData = ExAllocatePoolWithTag(PagedPool,
  1279. ValueLength,
  1280. VP_TAG);
  1281. if (ValueData) {
  1282. ULONG j, k;
  1283. WCHAR HexDigit[] = {L"0123456789ABCDEF"};
  1284. //
  1285. // Convert the AccessRanges into Unicode.
  1286. //
  1287. p = (PWCHAR) ValueData;
  1288. pulData = (PULONG)SaveAccessRanges;
  1289. for (j=0; j<NumAccessRanges * 4; j++) {
  1290. for (k=0; k<8; k++) {
  1291. *p++ = HexDigit[0xf & (*pulData >> ((7-k) * 4))];
  1292. }
  1293. if ((j % 4) != 3) *p++ = (WCHAR) L' ';
  1294. else *p++ = UNICODE_NULL;
  1295. pulData++;
  1296. }
  1297. *p = UNICODE_NULL;
  1298. RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
  1299. DoSpecificExtension->DriverRegistryPath,
  1300. L"RequestedResources",
  1301. REG_MULTI_SZ,
  1302. ValueData,
  1303. ValueLength);
  1304. ExFreePool(ValueData);
  1305. }
  1306. }
  1307. #endif
  1308. if (FdoExtension->ResourceList) {
  1309. ExFreePool(FdoExtension->ResourceList);
  1310. }
  1311. FdoExtension->ResourceList = resourceList;
  1312. //
  1313. // This is for hive compatibility back when we have the VGA driver
  1314. // as opposed to VgaSave.
  1315. // The Vga also cleans up the resource automatically.
  1316. //
  1317. //
  1318. // If we tried to override the conflict, let's take a look a what
  1319. // we want to do with the result
  1320. //
  1321. if ((NT_SUCCESS(ntStatus)) &&
  1322. overrideConflict &&
  1323. *Conflict) {
  1324. //
  1325. // For cases like Detection, a conflict is bad and we do
  1326. // want to fail.
  1327. //
  1328. // In the case of Basevideo, a conflict is possible. But we still
  1329. // want to load the VGA anyways. Return success and reset the
  1330. // conflict flag !
  1331. //
  1332. // pOverrideConflict with the FALSE flag will check that.
  1333. //
  1334. if (pOverrideConflict(FdoExtension, FALSE)) {
  1335. VpReleaseResources(FdoExtension);
  1336. ntStatus = STATUS_CONFLICTING_ADDRESSES;
  1337. } else {
  1338. *Conflict = FALSE;
  1339. ntStatus = STATUS_SUCCESS;
  1340. }
  1341. }
  1342. return ntStatus;
  1343. }
  1344. } // end pVideoPortBuildResourceList()
  1345. VP_STATUS
  1346. VideoPortVerifyAccessRanges(
  1347. PVOID HwDeviceExtension,
  1348. ULONG NumAccessRanges,
  1349. PVIDEO_ACCESS_RANGE AccessRanges
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. VideoPortVerifyAccessRanges
  1354. Arguments:
  1355. HwDeviceExtension - Points to the miniport driver's device extension.
  1356. NumAccessRanges - Number of entries in the AccessRanges array.
  1357. AccessRanges - Pointer to an array of AccessRanges the miniport driver
  1358. wants to access.
  1359. Return Value:
  1360. ERROR_INVALID_PARAMETER in an error occured
  1361. NO_ERROR if the call completed successfully
  1362. Environment:
  1363. This routine cannot be called from a miniport routine synchronized with
  1364. VideoPortSynchronizeRoutine or from an ISR.
  1365. --*/
  1366. {
  1367. NTSTATUS status;
  1368. BOOLEAN conflict;
  1369. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  1370. //
  1371. // According to the DDK docs, you can free all your resources by
  1372. // calling VideoPortVerifyAccessRanges with NumAccessRanges = 0.
  1373. //
  1374. if (NumAccessRanges == 0) {
  1375. VpReleaseResources(fdoExtension);
  1376. }
  1377. //
  1378. // If the device is not enabled then we won't allow the miniport
  1379. // to claim resources for it.
  1380. //
  1381. if (!CheckIoEnabled(
  1382. HwDeviceExtension,
  1383. NumAccessRanges,
  1384. AccessRanges)) {
  1385. return ERROR_INVALID_PARAMETER;
  1386. }
  1387. //
  1388. // All resources not passed in during the START_DEVICE irp should
  1389. // be claimed on the FDO. We will strip out the PDO resources
  1390. // in pVideoPortReportResourceList if the miniport driver tries
  1391. // to verify ranges acquired through VideoPortGetAccessRanges.
  1392. //
  1393. status = pVideoPortReportResourceList(
  1394. GET_DSP_EXT(HwDeviceExtension),
  1395. NumAccessRanges,
  1396. AccessRanges,
  1397. &conflict,
  1398. fdoExtension->FunctionalDeviceObject,
  1399. TRUE
  1400. );
  1401. //
  1402. // If we're upgrading, don't worry if the VGA driver can't get the
  1403. // resources. Some older legacy driver may be loaded that consumes
  1404. // those resources.
  1405. //
  1406. if ((VpSetupType == SETUPTYPE_UPGRADE) &&
  1407. (fdoExtension->Flags & VGA_DRIVER) )
  1408. {
  1409. status = STATUS_SUCCESS;
  1410. conflict = 0;
  1411. }
  1412. if ((NT_SUCCESS(status)) && (!conflict)) {
  1413. //
  1414. // Track the resources owned by the VGA driver.
  1415. //
  1416. if (fdoExtension->Flags & VGA_DRIVER) {
  1417. if (VgaAccessRanges != AccessRanges) {
  1418. ULONG Size = NumAccessRanges * sizeof(VIDEO_ACCESS_RANGE);
  1419. if (VgaAccessRanges) {
  1420. ExFreePool(VgaAccessRanges);
  1421. VgaAccessRanges = NULL;
  1422. NumVgaAccessRanges = 0;
  1423. }
  1424. if (NumAccessRanges) {
  1425. VgaAccessRanges = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, Size, VP_TAG);
  1426. if (VgaAccessRanges) {
  1427. memcpy(VgaAccessRanges, AccessRanges, Size);
  1428. NumVgaAccessRanges = NumAccessRanges;
  1429. }
  1430. }
  1431. }
  1432. }
  1433. return NO_ERROR;
  1434. } else {
  1435. return ERROR_INVALID_PARAMETER;
  1436. }
  1437. } // end VideoPortVerifyAccessRanges()
  1438. BOOLEAN
  1439. CheckIoEnabled(
  1440. PVOID HwDeviceExtension,
  1441. ULONG NumAccessRanges,
  1442. PVIDEO_ACCESS_RANGE AccessRanges
  1443. )
  1444. /*++
  1445. Routine Description:
  1446. This routine ensures that IO is actually enabled if claiming
  1447. IO ranges.
  1448. Arguments:
  1449. HwDeviceExtension - Points to the miniport driver's device extension.
  1450. NumAccessRanges - Number of entries in the AccessRanges array.
  1451. AccessRanges - Pointer to an array of AccessRanges the miniport driver
  1452. wants to access.
  1453. Return Value:
  1454. TRUE if our IO access checks pass,
  1455. FALSE otherwise.
  1456. --*/
  1457. {
  1458. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  1459. if (fdoExtension->Flags & LEGACY_DRIVER) {
  1460. //
  1461. // We will always return TRUE for legacy drivers.
  1462. //
  1463. return TRUE;
  1464. }
  1465. if (fdoExtension->AdapterInterfaceType == PCIBus) {
  1466. //
  1467. // Check to see if there are any IO ranges in the
  1468. // list or resources.
  1469. //
  1470. ULONG i;
  1471. USHORT Command;
  1472. ULONG byteCount;
  1473. //
  1474. // Get the PCI Command register for this device.
  1475. //
  1476. byteCount = VideoPortGetBusData(
  1477. HwDeviceExtension,
  1478. PCIConfiguration,
  1479. 0,
  1480. &Command,
  1481. FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
  1482. sizeof(USHORT));
  1483. //
  1484. // If the following test fails it means we couldn't get at
  1485. // the I/O bits in the config space. Assume that the I/O is
  1486. // on and proceed.
  1487. //
  1488. if (byteCount != sizeof (USHORT)) {
  1489. ASSERT(FALSE);
  1490. return TRUE;
  1491. }
  1492. for (i=0; i<NumAccessRanges; i++) {
  1493. if (AccessRanges[i].RangeInIoSpace) {
  1494. if (!(Command & PCI_ENABLE_IO_SPACE))
  1495. return FALSE;
  1496. } else {
  1497. if (!(Command & PCI_ENABLE_MEMORY_SPACE))
  1498. return FALSE;
  1499. }
  1500. }
  1501. return TRUE;
  1502. } else {
  1503. //
  1504. // Non-pci devices will always decode IO operations.
  1505. //
  1506. return TRUE;
  1507. }
  1508. }
  1509. BOOLEAN
  1510. VpIsLegacyAccessRange(
  1511. PFDO_EXTENSION fdoExtension,
  1512. PVIDEO_ACCESS_RANGE AccessRange
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. This return determines whether a given access range is
  1517. included in the list of legacy access ranges.
  1518. Arguments:
  1519. fdoExtension - The FDO extension for the device using the access range.
  1520. AccessRange - The access range to look for in the resource list.
  1521. Returns:
  1522. TRUE if the given access range is included in the list of reported
  1523. legacy resources, FALSE otherwise.
  1524. --*/
  1525. {
  1526. ULONG i;
  1527. PVIDEO_ACCESS_RANGE CurrResource;
  1528. if (fdoExtension->HwLegacyResourceList) {
  1529. CurrResource = fdoExtension->HwLegacyResourceList;
  1530. for (i=0; i<fdoExtension->HwLegacyResourceCount; i++) {
  1531. if ((CurrResource->RangeStart.QuadPart ==
  1532. AccessRange->RangeStart.QuadPart) &&
  1533. (CurrResource->RangeLength == AccessRange->RangeLength)) {
  1534. return TRUE;
  1535. }
  1536. CurrResource++;
  1537. }
  1538. }
  1539. return FALSE;
  1540. }
  1541. ULONG
  1542. GetCmResourceListSize(
  1543. PCM_RESOURCE_LIST CmResourceList
  1544. )
  1545. /*++
  1546. Routine Description:
  1547. Get the size in bytes of a CmResourceList.
  1548. Arguments:
  1549. CmResourceList - The list for which to get the size.
  1550. Returns:
  1551. Size in bytes of the CmResourceList.
  1552. --*/
  1553. {
  1554. PCM_FULL_RESOURCE_DESCRIPTOR pcmFull;
  1555. PCM_PARTIAL_RESOURCE_LIST pcmPartial;
  1556. PCM_PARTIAL_RESOURCE_DESCRIPTOR pcmDescript;
  1557. ULONG i, j;
  1558. pcmFull = &(CmResourceList->List[0]);
  1559. for (i=0; i<CmResourceList->Count; i++) {
  1560. pcmPartial = &(pcmFull->PartialResourceList);
  1561. pcmDescript = &(pcmPartial->PartialDescriptors[0]);
  1562. pcmDescript += pcmPartial->Count;
  1563. pcmFull = (PCM_FULL_RESOURCE_DESCRIPTOR) pcmDescript;
  1564. }
  1565. return (ULONG)(((ULONG_PTR)pcmFull) - ((ULONG_PTR)CmResourceList));
  1566. }
  1567. PCM_RESOURCE_LIST
  1568. VpRemoveFromResourceList(
  1569. PCM_RESOURCE_LIST OriginalList,
  1570. ULONG NumAccessRanges,
  1571. PVIDEO_ACCESS_RANGE AccessRanges
  1572. )
  1573. /*++
  1574. Routine Description:
  1575. Creates a new CmResourceList with the given access ranges
  1576. removed.
  1577. Arguments:
  1578. OriginalList - The original CmResourceList to operate on.
  1579. NumAccessRanges - The number of entries in the remove list.
  1580. AccessRanges - The list of ranges which should be removed from
  1581. the list.
  1582. Returns:
  1583. A pointer to the new CmResourceList.
  1584. Notes:
  1585. The caller is responsible for freeing the memory returned by this
  1586. function.
  1587. --*/
  1588. {
  1589. PCM_RESOURCE_LIST FilteredList;
  1590. ULONG Size = GetCmResourceListSize(OriginalList);
  1591. ULONG remainingLength;
  1592. ULONG ResourcesRemoved;
  1593. FilteredList = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, Size, VP_TAG);
  1594. if (FilteredList) {
  1595. ULONG i, j, k;
  1596. PCM_FULL_RESOURCE_DESCRIPTOR pcmFull;
  1597. PCM_PARTIAL_RESOURCE_LIST pcmPartial;
  1598. PCM_PARTIAL_RESOURCE_DESCRIPTOR pcmDescript;
  1599. //
  1600. // Make a copy of the original list.
  1601. //
  1602. memcpy(FilteredList, OriginalList, Size);
  1603. remainingLength = Size - sizeof(CM_RESOURCE_LIST);
  1604. pcmFull = &(FilteredList->List[0]);
  1605. for (i=0; i<FilteredList->Count; i++) {
  1606. pcmPartial = &(pcmFull->PartialResourceList);
  1607. pcmDescript = &(pcmPartial->PartialDescriptors[0]);
  1608. ResourcesRemoved = 0;
  1609. for (j=0; j<pcmPartial->Count; j++) {
  1610. //
  1611. // See if the current resource is in our legacy list.
  1612. //
  1613. for (k=0; k<NumAccessRanges; k++) {
  1614. if ((pcmDescript->u.Memory.Start.LowPart ==
  1615. AccessRanges[k].RangeStart.LowPart) &&
  1616. (AccessRanges[k].RangeStart.LowPart != 0xC0000)) {
  1617. //
  1618. // Remove the resource.
  1619. //
  1620. memmove(pcmDescript,
  1621. pcmDescript + 1,
  1622. remainingLength);
  1623. pcmDescript--;
  1624. ResourcesRemoved++;
  1625. break;
  1626. }
  1627. }
  1628. remainingLength -= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1629. pcmDescript++;
  1630. }
  1631. //
  1632. // Update the resource count in the partial resource list
  1633. //
  1634. pcmPartial->Count -= ResourcesRemoved;
  1635. if (pcmPartial->Count == 0) {
  1636. FilteredList->Count--;
  1637. }
  1638. remainingLength -= sizeof(CM_PARTIAL_RESOURCE_LIST);
  1639. pcmFull = (PCM_FULL_RESOURCE_DESCRIPTOR) pcmDescript;
  1640. }
  1641. } else {
  1642. //
  1643. // Make sure we always return a list.
  1644. //
  1645. ASSERT(FALSE);
  1646. FilteredList = OriginalList;
  1647. }
  1648. return FilteredList;
  1649. }