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.

1160 lines
33 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. Common initialization routine for the AGP filter driver
  7. Author:
  8. John Vert (jvert) 10/22/1997
  9. Revision History:
  10. Elliot Shmukler (elliots) 3/24/1999 - Added support for "favored" memory
  11. ranges for AGP physical memory allocation,
  12. fixed some bugs.
  13. --*/
  14. #include "agplib.h"
  15. //
  16. // Local function prototypes
  17. //
  18. NTSTATUS
  19. AgpAddDevice(
  20. IN PDRIVER_OBJECT DriverObject,
  21. IN PDEVICE_OBJECT PhysicalDeviceObject
  22. );
  23. NTSTATUS
  24. AgpBuildHackTable(
  25. IN OUT PAGP_HACK_TABLE_ENTRY *AgpHackTable,
  26. IN HANDLE HackTableKey
  27. );
  28. NTSTATUS
  29. DriverEntry(
  30. IN PDRIVER_OBJECT DriverObject,
  31. IN PUNICODE_STRING RegistryPath
  32. );
  33. VOID
  34. AgpDriverUnload(
  35. IN PDRIVER_OBJECT DriverObject
  36. );
  37. VOID
  38. AgpInitFavoredMemoryRanges(
  39. IN PTARGET_EXTENSION Extension);
  40. #ifdef ALLOC_PRAGMA
  41. #pragma alloc_text(PAGE, AgpAddDevice)
  42. #pragma alloc_text(PAGE, DriverEntry)
  43. #pragma alloc_text(PAGE, AgpDriverUnload)
  44. #pragma alloc_text(PAGE, AgpAttachDeviceRelations)
  45. #pragma alloc_text(INIT, AgpBuildHackTable)
  46. #pragma alloc_text(PAGE, AgpInitFavoredMemoryRanges)
  47. #endif
  48. ULONG AgpLogLevel = 0;
  49. ULONG AgpStopLevel = 0;
  50. PDRIVER_OBJECT AgpDriver;
  51. GLOBALS Globals;
  52. //
  53. // Table of hacks for broken hardware read from the registry at init
  54. //
  55. PAGP_HACK_TABLE_ENTRY AgpDeviceHackTable = NULL;
  56. PAGP_HACK_TABLE_ENTRY AgpGlobalHackTable = NULL;
  57. #define HACKFMT_VENDORDEV (sizeof(L"VVVVDDDD") - sizeof(UNICODE_NULL))
  58. #define HACKFMT_VENDORDEVREVISION (sizeof(L"VVVVDDDDRR") - sizeof(UNICODE_NULL))
  59. #define HACKFMT_SUBSYSTEM (sizeof(L"VVVVDDDDSSSSssss") - sizeof(UNICODE_NULL))
  60. #define HACKFMT_SUBSYSTEMREVISION (sizeof(L"VVVVDDDDSSSSssssRR") - sizeof(UNICODE_NULL))
  61. #define HACKFMT_MAX_LENGTH HACKFMT_SUBSYSTEMREVISION
  62. #define HACKFMT_DEVICE_OFFSET 4
  63. #define HACKFMT_SUBVENDOR_OFFSET 8
  64. #define HACKFMT_SUBSYSTEM_OFFSET 12
  65. NTSTATUS
  66. AgpAddDevice(
  67. IN PDRIVER_OBJECT DriverObject,
  68. IN PDEVICE_OBJECT PhysicalDeviceObject
  69. )
  70. {
  71. NTSTATUS Status;
  72. PDEVICE_OBJECT Device;
  73. PTARGET_EXTENSION Extension;
  74. UCHAR CapabilityID;
  75. PAGED_CODE();
  76. //
  77. // Create our device
  78. //
  79. Status = IoCreateDevice(DriverObject,
  80. sizeof(TARGET_EXTENSION) + AgpExtensionSize - sizeof(ULONGLONG),
  81. NULL,
  82. FILE_DEVICE_BUS_EXTENDER,
  83. FILE_DEVICE_SECURE_OPEN, // Not really necessary in our case as we don't support create
  84. FALSE,
  85. &Device);
  86. if (!NT_SUCCESS(Status)) {
  87. AGPLOG(AGP_CRITICAL,("AgpAddDevice: IoCreateDevice failed %08lx\n",Status));
  88. return(Status);
  89. }
  90. //
  91. // Initialize the device extension
  92. //
  93. Extension = Device->DeviceExtension;
  94. Extension->CommonExtension.Type = AgpTargetFilter;
  95. Extension->CommonExtension.Deleted = FALSE;
  96. Extension->CommonExtension.Signature = TARGET_SIG;
  97. #if (WINVER > 0x501)
  98. Status =
  99. ApQueryAgpTargetBusInterface(PhysicalDeviceObject,
  100. &Extension->CommonExtension.BusInterface,
  101. &CapabilityID);
  102. #else
  103. Status = STATUS_NOT_IMPLEMENTED;
  104. #endif // (WINVER > 0x501)
  105. //
  106. // Perhaps this OS doesn't support the new AGP_TARGET_BUS_INTERFACE, then
  107. // we can still support the target bridge without using HalGet/SetBusData
  108. // we just have to do a bit more work, and probe to see if there is an AGP
  109. // target capability on this bridge device
  110. //
  111. #ifndef AGP_INTERFACE_TEST
  112. if (!NT_SUCCESS(Status)) {
  113. Status = ApQueryBusInterface(PhysicalDeviceObject,
  114. &Extension->CommonExtension.BusInterface);
  115. if (NT_SUCCESS(Status)) {
  116. PCI_AGP_CAPABILITY TargetCap;
  117. //
  118. // Look for the target bride capability
  119. //
  120. Status = AgpLibGetTargetCapability(GET_AGP_CONTEXT(Extension),
  121. &TargetCap);
  122. if (NT_SUCCESS(Status)) {
  123. CapabilityID = TargetCap.Header.CapabilityID;
  124. //
  125. // For our UAGP35 driver to work on older OS, we will
  126. // attempt to override the bus interface with
  127. // HalGet/SetBusData functions that access the host, if
  128. // we can find an AGP capability there, otherwise we
  129. // will leave well enough alone so other drivers will
  130. // continue to get the same behavior they've always had,
  131. // namely bus interface still munges whatever, and lib
  132. // behavior defaults to traditional/non-bridge w/respect
  133. // to resource handling
  134. //
  135. } else {
  136. BUS_INTERFACE_STANDARD BusInterfaceSave;
  137. CapabilityID = PCI_CAPABILITY_ID_AGP;
  138. #if (WINVER < 0x502)
  139. //
  140. // Save the bus interface
  141. //
  142. BusInterfaceSave.SetBusData =
  143. Extension->CommonExtension.BusInterface.SetBusData;
  144. BusInterfaceSave.GetBusData =
  145. Extension->CommonExtension.BusInterface.GetBusData;
  146. Extension->CommonExtension.BusInterface.SetBusData =
  147. ApLegacySetBusData;
  148. Extension->CommonExtension.BusInterface.GetBusData =
  149. ApLegacyGetBusData;
  150. Status = AgpLibGetTargetCapability(GET_AGP_CONTEXT(Extension),
  151. &TargetCap);
  152. if (!NT_SUCCESS(Status)) {
  153. Extension->CommonExtension.BusInterface.SetBusData =
  154. BusInterfaceSave.SetBusData;
  155. Extension->CommonExtension.BusInterface.GetBusData =
  156. BusInterfaceSave.GetBusData;
  157. }
  158. #endif // (WINVER < 0x502)
  159. Status = STATUS_SUCCESS; // We do have a bus interface
  160. }
  161. }
  162. }
  163. #endif // AGP_INTERFACE_TEST
  164. if (!NT_SUCCESS(Status)) {
  165. AGPLOG(AGP_CRITICAL,
  166. ("AgpAddDevice: query for bus interface failed %08lx\n", Status));
  167. IoDeleteDevice(Device);
  168. return(STATUS_NO_SUCH_DEVICE);
  169. }
  170. Extension->ChildDevice = NULL;
  171. Extension->Resources = NULL;
  172. Extension->ResourcesTranslated = NULL;
  173. Extension->FavoredMemory.NumRanges = 0;
  174. Extension->FavoredMemory.Ranges = NULL;
  175. Extension->GartBase.QuadPart = 0;
  176. Extension->GartLengthInPages = 0;
  177. Extension->Agp3BridgeResourceIndex = JUNK_INDEX;
  178. if (CapabilityID == PCI_CAPABILITY_ID_AGP_TARGET) {
  179. Extension->StartTarget = Agp3StartTargetBridge;
  180. Extension->FilterResourceRquirements =
  181. Agp3FilterResourceRequirementsBridge;
  182. } else {
  183. ASSERT(CapabilityID == PCI_CAPABILITY_ID_AGP);
  184. Extension->StartTarget = AgpStartTargetHost;
  185. Extension->FilterResourceRquirements =
  186. AgpFilterResourceRequirementsHost;
  187. }
  188. Extension->Lock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), 'MFgA');
  189. if (Extension->Lock == NULL) {
  190. AGPLOG(AGP_CRITICAL,
  191. ("AgpAddDevice: allocation of fast mutext failed\n"));
  192. RELEASE_BUS_INTERFACE(Extension);
  193. IoDeleteDevice(Device);
  194. return(STATUS_INSUFFICIENT_RESOURCES);
  195. }
  196. ExInitializeFastMutex(Extension->Lock);
  197. //
  198. // Attach to the supplied PDO
  199. //
  200. Extension->CommonExtension.AttachedDevice = IoAttachDeviceToDeviceStack(Device, PhysicalDeviceObject);
  201. if (Extension->CommonExtension.AttachedDevice == NULL) {
  202. //
  203. // The attach failed.
  204. //
  205. AGPLOG(AGP_CRITICAL,
  206. ("AgpAddDevice: IoAttachDeviceToDeviceStack from %08lx to %08lx failed\n",
  207. Device,
  208. PhysicalDeviceObject));
  209. RELEASE_BUS_INTERFACE(Extension);
  210. IoDeleteDevice(Device);
  211. return(STATUS_INSUFFICIENT_RESOURCES);
  212. }
  213. //
  214. // Figure out our favored memory ranges
  215. //
  216. AgpInitFavoredMemoryRanges(Extension);
  217. //
  218. // Finally call the chipset-specific code for target initialization
  219. //
  220. Status = AgpInitializeTarget(GET_AGP_CONTEXT(Extension));
  221. if (!NT_SUCCESS(Status)) {
  222. AGPLOG(AGP_CRITICAL,
  223. ("AgpAttachDeviceRelations: AgpInitializeTarget on device %08lx failed %08lx\n",
  224. Device,
  225. Status));
  226. IoDetachDevice(Extension->CommonExtension.AttachedDevice);
  227. RELEASE_BUS_INTERFACE(Extension);
  228. IoDeleteDevice(Device);
  229. return(Status);
  230. }
  231. Extension->PDO = PhysicalDeviceObject;
  232. Extension->Self = Device;
  233. Status = AgpWmiRegistration(Extension);
  234. if (!NT_SUCCESS(Status)) {
  235. AGPLOG(AGP_CRITICAL, ("AgpWmiRegistration failed %08lx\n", Status));
  236. IoDetachDevice(Extension->CommonExtension.AttachedDevice);
  237. RELEASE_BUS_INTERFACE(Extension);
  238. IoDeleteDevice(Device);
  239. return Status;
  240. }
  241. Device->Flags &= ~DO_DEVICE_INITIALIZING;
  242. return(STATUS_SUCCESS);
  243. }
  244. NTSTATUS
  245. AgpBuildHackTable(
  246. IN OUT PAGP_HACK_TABLE_ENTRY *AgpHackTable,
  247. IN HANDLE HackTableKey
  248. )
  249. {
  250. NTSTATUS status;
  251. PKEY_FULL_INFORMATION keyInfo = NULL;
  252. ULONG hackCount, size, index;
  253. USHORT temp;
  254. PAGP_HACK_TABLE_ENTRY entry;
  255. ULONGLONG data;
  256. PKEY_VALUE_FULL_INFORMATION valueInfo = NULL;
  257. ULONG valueInfoSize = sizeof(KEY_VALUE_FULL_INFORMATION)
  258. + HACKFMT_MAX_LENGTH +
  259. + sizeof(ULONGLONG);
  260. //
  261. // Get the key info so we know how many hack values there are.
  262. // This does not change during system initialization.
  263. //
  264. status = ZwQueryKey(HackTableKey,
  265. KeyFullInformation,
  266. NULL,
  267. 0,
  268. &size
  269. );
  270. if (status != STATUS_BUFFER_TOO_SMALL) {
  271. ASSERT(!NT_SUCCESS(status));
  272. goto cleanup;
  273. }
  274. ASSERT(size > 0);
  275. keyInfo = ExAllocatePool(PagedPool, size);
  276. if (!keyInfo) {
  277. status = STATUS_INSUFFICIENT_RESOURCES;
  278. goto cleanup;
  279. }
  280. status = ZwQueryKey(HackTableKey,
  281. KeyFullInformation,
  282. keyInfo,
  283. size,
  284. &size
  285. );
  286. if (!NT_SUCCESS(status)) {
  287. goto cleanup;
  288. }
  289. hackCount = keyInfo->Values;
  290. ExFreePool(keyInfo);
  291. keyInfo = NULL;
  292. //
  293. // Allocate and initialize the hack table
  294. //
  295. *AgpHackTable = ExAllocatePool(NonPagedPool,
  296. (hackCount + 1) * sizeof(AGP_HACK_TABLE_ENTRY)
  297. );
  298. if (!*AgpHackTable) {
  299. status = STATUS_INSUFFICIENT_RESOURCES;
  300. goto cleanup;
  301. }
  302. //
  303. // Allocate a valueInfo buffer big enough for the biggest valid
  304. // format and a ULONGLONG worth of data.
  305. //
  306. valueInfo = ExAllocatePool(PagedPool, valueInfoSize);
  307. if (!valueInfo) {
  308. status = STATUS_INSUFFICIENT_RESOURCES;
  309. goto cleanup;
  310. }
  311. entry = *AgpHackTable;
  312. for (index = 0; index < hackCount; index++) {
  313. status = ZwEnumerateValueKey(HackTableKey,
  314. index,
  315. KeyValueFullInformation,
  316. valueInfo,
  317. valueInfoSize,
  318. &size
  319. );
  320. if (!NT_SUCCESS(status)) {
  321. if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL) {
  322. //
  323. // All out data is of fixed length and the buffer is big enough
  324. // so this can't be for us.
  325. //
  326. continue;
  327. } else {
  328. goto cleanup;
  329. }
  330. }
  331. //
  332. // Get pointer to the data if its of the right type
  333. //
  334. if ((valueInfo->Type == REG_BINARY) &&
  335. (valueInfo->DataLength == sizeof(ULONGLONG))) {
  336. data = *(ULONGLONG UNALIGNED *)(((PUCHAR)valueInfo) + valueInfo->DataOffset);
  337. } else {
  338. //
  339. // We only deal in ULONGLONGs
  340. //
  341. continue;
  342. }
  343. //
  344. // Now see if the name is formatted like we expect it to be:
  345. // VVVVDDDD
  346. // VVVVDDDDRR
  347. // VVVVDDDDSSSSssss
  348. // VVVVDDDDSSSSssssRR
  349. if ((valueInfo->NameLength != HACKFMT_VENDORDEV) &&
  350. (valueInfo->NameLength != HACKFMT_VENDORDEVREVISION) &&
  351. (valueInfo->NameLength != HACKFMT_SUBSYSTEM) &&
  352. (valueInfo->NameLength != HACKFMT_SUBSYSTEMREVISION)) {
  353. //
  354. // This isn't ours
  355. //
  356. AGPLOG(
  357. AGP_CRITICAL,
  358. ("Skipping hack entry with invalid length name\n"
  359. ));
  360. continue;
  361. }
  362. //
  363. // This looks plausable - try to parse it and fill in a hack table
  364. // entry
  365. //
  366. RtlZeroMemory(entry, sizeof(AGP_HACK_TABLE_ENTRY));
  367. //
  368. // Look for DeviceID and VendorID (VVVVDDDD)
  369. //
  370. if (!AgpStringToUSHORT(valueInfo->Name, &entry->VendorID)) {
  371. continue;
  372. }
  373. if (!AgpStringToUSHORT(valueInfo->Name + HACKFMT_DEVICE_OFFSET,
  374. &entry->DeviceID)) {
  375. continue;
  376. }
  377. //
  378. // Look for SubsystemVendorID/SubSystemID (SSSSssss)
  379. //
  380. if ((valueInfo->NameLength == HACKFMT_SUBSYSTEM) ||
  381. (valueInfo->NameLength == HACKFMT_SUBSYSTEMREVISION)) {
  382. if (!AgpStringToUSHORT(valueInfo->Name + HACKFMT_SUBVENDOR_OFFSET,
  383. &entry->SubVendorID)) {
  384. continue;
  385. }
  386. if (!AgpStringToUSHORT(valueInfo->Name + HACKFMT_SUBSYSTEM_OFFSET,
  387. &entry->SubSystemID)) {
  388. continue;
  389. }
  390. entry->Flags |= AGP_HACK_FLAG_SUBSYSTEM;
  391. }
  392. //
  393. // Look for RevisionID (RR)
  394. //
  395. if ((valueInfo->NameLength == HACKFMT_VENDORDEVREVISION) ||
  396. (valueInfo->NameLength == HACKFMT_SUBSYSTEMREVISION)) {
  397. if (AgpStringToUSHORT(valueInfo->Name +
  398. (valueInfo->NameLength/sizeof(WCHAR) - 4), &temp)) {
  399. entry->RevisionID = temp & 0xFF;
  400. entry->Flags |= AGP_HACK_FLAG_REVISION;
  401. } else {
  402. continue;
  403. }
  404. }
  405. ASSERT(entry->VendorID != 0xFFFF);
  406. //
  407. // Fill in the entry
  408. //
  409. entry->DeviceFlags = data;
  410. AGPLOG(
  411. AGP_CRITICAL,
  412. ("Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
  413. entry->VendorID, entry->DeviceID
  414. ));
  415. if (entry->Flags & AGP_HACK_FLAG_SUBSYSTEM) {
  416. AGPLOG(
  417. AGP_CRITICAL,
  418. ("SybSys:0x%04x SubVendor:0x%04x ",
  419. entry->SubSystemID, entry->SubVendorID
  420. ));
  421. }
  422. if (entry->Flags & AGP_HACK_FLAG_REVISION) {
  423. AGPLOG(
  424. AGP_CRITICAL,
  425. ("Revision:0x%02x",
  426. (ULONG) entry->RevisionID
  427. ));
  428. }
  429. AGPLOG(
  430. AGP_CRITICAL,
  431. (" = 0x%I64x\n",
  432. entry->DeviceFlags
  433. ));
  434. entry++;
  435. }
  436. ASSERT(entry < (*AgpHackTable + hackCount + 1));
  437. //
  438. // Terminate the table with an invalid VendorID
  439. //
  440. entry->VendorID = 0xFFFF;
  441. ExFreePool(valueInfo);
  442. return STATUS_SUCCESS;
  443. cleanup:
  444. ASSERT(!NT_SUCCESS(status));
  445. if (keyInfo) {
  446. ExFreePool(keyInfo);
  447. }
  448. if (valueInfo) {
  449. ExFreePool(valueInfo);
  450. }
  451. if (*AgpHackTable) {
  452. ExFreePool(*AgpHackTable);
  453. *AgpHackTable = NULL;
  454. }
  455. return status;
  456. }
  457. VOID
  458. AgpInitFavoredMemoryRanges(
  459. IN PTARGET_EXTENSION Extension)
  460. /*++
  461. Routine Description:
  462. Determines the optimum memory ranges for AGP physical memory
  463. allocation by calling the ACPI BANK method provided by the
  464. AGP northbridge in order to determine which physical memory
  465. ranges are decoded by that northbridge.
  466. Initializes the FavoredMemory sturcture in the target extension
  467. with the proper ranges.
  468. If this routine fails, then the FavoredMemory structure
  469. is left untouched in its initialized state (i.e. no favored memory
  470. ranges found).
  471. Arguments:
  472. Extension - The target extension.
  473. Return Value:
  474. NONE. Upon failure,
  475. --*/
  476. {
  477. PDEVICE_OBJECT LowerPdo;
  478. IO_STATUS_BLOCK IoStatus;
  479. PIRP Irp;
  480. KEVENT event;
  481. NTSTATUS Status;
  482. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  483. UCHAR ResultBuffer[sizeof(ACPI_EVAL_OUTPUT_BUFFER) + MAX_MBAT_SIZE];
  484. PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  485. PACPI_METHOD_ARGUMENT MethodArg;
  486. PMBAT Mbat;
  487. UCHAR i;
  488. USHORT j;
  489. PHYSICAL_ADDRESS MaxMemory;
  490. //
  491. // Maximum memory address for limiting AGP memory to below 4GB
  492. //
  493. MAX_MEM(MaxMemory.QuadPart);
  494. //
  495. // Get an event to wait on
  496. //
  497. KeInitializeEvent(&event, NotificationEvent, FALSE);
  498. // Get a PDO where we will send the request IRP.
  499. LowerPdo = Extension->CommonExtension.AttachedDevice;
  500. //
  501. // Initialize the input parameters and the output buffer.
  502. //
  503. RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
  504. inputBuffer.MethodNameAsUlong = CM_BANK_METHOD;
  505. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  506. outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)ResultBuffer;
  507. //
  508. // Build the request to call the BANK method.
  509. //
  510. Irp = IoBuildDeviceIoControlRequest(
  511. IOCTL_ACPI_EVAL_METHOD,
  512. LowerPdo,
  513. &inputBuffer,
  514. sizeof(ACPI_EVAL_INPUT_BUFFER),
  515. outputBuffer,
  516. sizeof(ResultBuffer),
  517. FALSE,
  518. &event,
  519. &IoStatus
  520. );
  521. if (!Irp)
  522. {
  523. return;
  524. }
  525. //
  526. // Send to the ACPI driver
  527. //
  528. Status = IoCallDriver ( LowerPdo, Irp);
  529. if (Status == STATUS_PENDING)
  530. {
  531. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL);
  532. Status = IoStatus.Status;
  533. }
  534. if (NT_SUCCESS(Status))
  535. {
  536. AGPLOG(AGP_NOISE, ("AGPLIB: ACPI BANK Method Executed.\n"));
  537. //
  538. // Sanity check method results
  539. //
  540. MethodArg = outputBuffer->Argument;
  541. if ((outputBuffer->Signature == ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) &&
  542. (MethodArg->DataLength >= sizeof(MBAT)) &&
  543. (MethodArg->Type == ACPI_METHOD_ARGUMENT_BUFFER))
  544. {
  545. AGPLOG(AGP_NOISE, ("AGPLIB: MBAT appears valid.\n"));
  546. //
  547. // Grab the MBAT and see if we can parse it
  548. //
  549. Mbat = (PMBAT)MethodArg->Data;
  550. if (Mbat->TableVersion == MBAT_VERSION) {
  551. AGPLOG(AGP_NOISE, ("AGPLIB: Parsing MBAT.\n"));
  552. //
  553. // Calculate the number of favored ranges mentioned
  554. // in the MBAT
  555. //
  556. i=Mbat->ValidEntryBitmap;
  557. while(i)
  558. {
  559. Extension->FavoredMemory.NumRanges++;
  560. i = i & (i-1);
  561. }
  562. AGPLOG(AGP_NOISE, ("AGPLIB: %u favored ranges found.\n",
  563. Extension->FavoredMemory.NumRanges));
  564. if(Extension->FavoredMemory.NumRanges == 0) return;
  565. //
  566. // Allocate the favored memory range structure in our device
  567. // extension
  568. //
  569. Extension->FavoredMemory.Ranges =
  570. ExAllocatePool(NonPagedPool, sizeof(AGP_MEMORY_RANGE) *
  571. Extension->FavoredMemory.NumRanges);
  572. if (Extension->FavoredMemory.Ranges == NULL) {
  573. Extension->FavoredMemory.NumRanges = 0;
  574. return;
  575. }
  576. //
  577. // Initialize the favored memory ranges in our extension
  578. // based upon the MBAT
  579. //
  580. i=0;
  581. j=0;
  582. while(Mbat->ValidEntryBitmap)
  583. {
  584. if (Mbat->ValidEntryBitmap & 1)
  585. {
  586. if (Mbat->DecodeRange[i].Lower.QuadPart > MaxMemory.QuadPart) {
  587. // This range is invalid since its lower address is above
  588. // the highest allowable address
  589. AGPLOG(AGP_NOISE, ("AGPLIB: Invalid MBAT Range ==> %I64x - %I64x\n",
  590. Mbat->DecodeRange[i].Lower.QuadPart,
  591. Mbat->DecodeRange[i].Upper.QuadPart));
  592. // Pretend like this range never existed ...
  593. //
  594. Extension->FavoredMemory.NumRanges--;
  595. }
  596. else
  597. {
  598. // This is a valid range.
  599. Extension->FavoredMemory.Ranges[j].Lower.QuadPart =
  600. Mbat->DecodeRange[i].Lower.QuadPart;
  601. Extension->FavoredMemory.Ranges[j].Upper.QuadPart =
  602. Mbat->DecodeRange[i].Upper.QuadPart;
  603. AGPLOG(AGP_NOISE, ("AGPLIB: MBAT Range ==> %I64x - %I64x\n",
  604. Mbat->DecodeRange[i].Lower.QuadPart,
  605. Mbat->DecodeRange[i].Upper.QuadPart));
  606. if(Extension->FavoredMemory.Ranges[j].Upper.QuadPart >
  607. MaxMemory.QuadPart)
  608. {
  609. AGPLOG(AGP_NOISE, ("AGPLIB: Adjusting range to fit within maximum allowable address.\n"));
  610. Extension->FavoredMemory.Ranges[j].Upper.QuadPart =
  611. MaxMemory.QuadPart;
  612. }
  613. j++;
  614. }
  615. }
  616. Mbat->ValidEntryBitmap >>= 1;
  617. i++;
  618. }
  619. } else {
  620. AGPLOG(AGP_WARNING, ("AGPLIB: Unknown MBAT version.\n"));
  621. }
  622. }
  623. }
  624. }
  625. NTSTATUS
  626. DriverEntry(
  627. IN PDRIVER_OBJECT DriverObject,
  628. IN PUNICODE_STRING RegistryPath
  629. )
  630. /*++
  631. Routine Description:
  632. Entrypoint needed to initialize the AGP filter.
  633. Arguments:
  634. DriverObject - Pointer to the driver object created by the system.
  635. RegistryPath - Pointer to the unicode registry service path.
  636. Return Value:
  637. NT status.
  638. --*/
  639. {
  640. NTSTATUS Status;
  641. HANDLE serviceKey, paramsKey;
  642. UNICODE_STRING UnicodeString;
  643. OBJECT_ATTRIBUTES attributes;
  644. PAGED_CODE();
  645. //
  646. // Save the RegistryPath for WMI
  647. //
  648. Globals.RegistryPath.MaximumLength =
  649. RegistryPath->Length + sizeof(UNICODE_NULL);
  650. Globals.RegistryPath.Length = RegistryPath->Length;
  651. Globals.RegistryPath.Buffer =
  652. ExAllocatePoolWithTag(PagedPool,
  653. Globals.RegistryPath.MaximumLength,
  654. 'GpgA'
  655. );
  656. if (!Globals.RegistryPath.Buffer) {
  657. return STATUS_INSUFFICIENT_RESOURCES;
  658. }
  659. RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);
  660. AgpDriver = DriverObject;
  661. DriverObject->DriverExtension->AddDevice = AgpAddDevice;
  662. DriverObject->DriverUnload = AgpDriverUnload;
  663. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AgpDispatchDeviceControl;
  664. DriverObject->MajorFunction[IRP_MJ_PNP] = AgpDispatchPnp;
  665. DriverObject->MajorFunction[IRP_MJ_POWER] = AgpDispatchPower;
  666. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AgpDispatchWmi;
  667. RtlInitUnicodeString(&UnicodeString,
  668. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
  669. L"Control");
  670. //
  671. // Open the global hack key and retrieve the gloabl hack table
  672. //
  673. InitializeObjectAttributes(&attributes,
  674. &UnicodeString,
  675. OBJ_CASE_INSENSITIVE,
  676. NULL,
  677. NULL
  678. );
  679. Status = ZwOpenKey(&serviceKey,
  680. KEY_READ,
  681. &attributes
  682. );
  683. //
  684. // We must succeed here, there are devices that can freeze a system,
  685. // and something is really wrong if we can't access these values
  686. //
  687. if (!NT_SUCCESS(Status)) {
  688. return Status;
  689. }
  690. AgpOpenKey(L"AGP", serviceKey, &paramsKey, &Status);
  691. ZwClose(serviceKey);
  692. if (!NT_SUCCESS(Status)) {
  693. return Status;
  694. }
  695. Status = AgpBuildHackTable(&AgpGlobalHackTable, paramsKey);
  696. ZwClose(paramsKey);
  697. if (!NT_SUCCESS(Status)) {
  698. return Status;
  699. }
  700. //
  701. // Open our service key and retrieve any platform hack(s)
  702. //
  703. InitializeObjectAttributes(&attributes,
  704. RegistryPath,
  705. OBJ_CASE_INSENSITIVE,
  706. NULL,
  707. NULL
  708. );
  709. Status = ZwOpenKey(&serviceKey,
  710. KEY_READ,
  711. &attributes
  712. );
  713. //
  714. // Maybe their chipset is so burly, it doesn't require any hacks!
  715. //
  716. if (!NT_SUCCESS(Status)) {
  717. return STATUS_SUCCESS;
  718. }
  719. AgpOpenKey(L"Parameters", serviceKey, &paramsKey, &Status);
  720. ZwClose(serviceKey);
  721. //
  722. // Don't care
  723. //
  724. if (!NT_SUCCESS(Status)) {
  725. return STATUS_SUCCESS;
  726. }
  727. //
  728. // Again, disregard status
  729. //
  730. AgpBuildHackTable(&AgpDeviceHackTable, paramsKey);
  731. ZwClose(paramsKey);
  732. return STATUS_SUCCESS;
  733. }
  734. VOID
  735. AgpDriverUnload(
  736. IN PDRIVER_OBJECT DriverObject
  737. )
  738. /*++
  739. Routine Description:
  740. Entrypoint used to unload the AGP driver
  741. Arguments:
  742. DriverObject - Pointer to the driver object created by the system
  743. Return Value:
  744. None
  745. --*/
  746. {
  747. if (AgpDeviceHackTable != NULL) {
  748. ExFreePool(AgpDeviceHackTable);
  749. AgpDeviceHackTable = NULL;
  750. }
  751. if (AgpGlobalHackTable != NULL) {
  752. ExFreePool(AgpGlobalHackTable);
  753. AgpGlobalHackTable = NULL;
  754. }
  755. if (Globals.RegistryPath.Buffer != NULL) {
  756. ExFreePool(Globals.RegistryPath.Buffer);
  757. Globals.RegistryPath.Buffer = NULL;
  758. }
  759. }
  760. NTSTATUS
  761. AgpAttachDeviceRelations(
  762. IN PDEVICE_OBJECT DeviceObject,
  763. IN PIRP Irp,
  764. IN PTARGET_EXTENSION Extension
  765. )
  766. /*++
  767. Routine Description:
  768. Completion routine for BusRelations IRP_MN_QUERY_DEVICE_RELATIONS irps sent
  769. to the PCI-PCI bridge PDO. In order to handle QUERY_INTERFACE irps sent
  770. from the AGP device, we must attach to its PDO. That means we attach to
  771. all the child PDOs of the PCI-PCI bridge.
  772. Arguments:
  773. DeviceObject - Supplies the device object
  774. Irp - Supplies the IRP_MN_QUERY_DEVICE_RELATIONS irp
  775. Extension - Supplies the AGP device extension.
  776. Return Value:
  777. NTSTATUS
  778. --*/
  779. {
  780. NTSTATUS Status;
  781. PDEVICE_RELATIONS Relations;
  782. ULONG i;
  783. PDEVICE_OBJECT NewDevice;
  784. PMASTER_EXTENSION NewExtension;
  785. AGP_CRITICAL_ROUTINE_CONTEXT routineContext;
  786. #if DBG
  787. ULONG MasterCount=0;
  788. #endif
  789. PAGED_CODE();
  790. //
  791. // If we have already attached, don't do it again.
  792. //
  793. if (Extension->ChildDevice != NULL) {
  794. return(STATUS_SUCCESS);
  795. }
  796. Relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
  797. //
  798. // If somebody completed the IRP with success, but never
  799. // filled in the Relations field, then assume there are
  800. // no children and we don't have to do anything.
  801. //
  802. if (Relations == NULL) {
  803. return(STATUS_SUCCESS);
  804. }
  805. for (i=0; i<Relations->Count; i++) {
  806. //
  807. // Create a device object to attach to this PDO.
  808. //
  809. Status = IoCreateDevice(AgpDriver,
  810. sizeof(MASTER_EXTENSION),
  811. NULL,
  812. FILE_DEVICE_BUS_EXTENDER,
  813. 0,
  814. FALSE,
  815. &NewDevice);
  816. if (!NT_SUCCESS(Status)) {
  817. AGPLOG(AGP_CRITICAL,("AgpAttachDeviceRelations: IoCreateDevice failed %08lx\n",Status));
  818. continue;
  819. }
  820. //
  821. // Initialize the device extension
  822. //
  823. NewExtension = NewDevice->DeviceExtension;
  824. NewExtension->CommonExtension.Deleted = FALSE;
  825. NewExtension->CommonExtension.Type = AgpMasterFilter;
  826. NewExtension->CommonExtension.Signature = MASTER_SIG;
  827. Status = ApQueryBusInterface(Relations->Objects[i], &NewExtension->CommonExtension.BusInterface);
  828. if (!NT_SUCCESS(Status)) {
  829. AGPLOG(AGP_CRITICAL,
  830. ("AgpAttachDeviceRelations: query for bus interface failed %08lx\n", Status));
  831. IoDeleteDevice(NewDevice);
  832. continue;
  833. }
  834. NewExtension->Target = Extension;
  835. NewExtension->InterfaceCount = 0;
  836. NewExtension->ReservedPages = 0;
  837. NewExtension->StopPending = FALSE;
  838. NewExtension->RemovePending = FALSE;
  839. NewExtension->DisableCount = 1; // biased so that we don't give anything out
  840. // until we see the IRP_MN_START
  841. Extension->ChildDevice = NewExtension;
  842. //
  843. // Attach to the specified device
  844. //
  845. NewExtension->CommonExtension.AttachedDevice = IoAttachDeviceToDeviceStack(NewDevice, Relations->Objects[i]);
  846. if (NewExtension->CommonExtension.AttachedDevice == NULL) {
  847. //
  848. // The attach failed. Not really fatal, AGP just won't work for that device.
  849. //
  850. AGPLOG(AGP_CRITICAL,
  851. ("AgpAttachDeviceRelations: IoAttachDeviceToDeviceStack from %08lx to %08lx failed\n",
  852. NewDevice,
  853. Relations->Objects[i]));
  854. RELEASE_BUS_INTERFACE(NewExtension);
  855. IoDeleteDevice(NewDevice);
  856. Extension->ChildDevice = NULL;
  857. continue;
  858. }
  859. //
  860. // Propagate the PDO's requirements
  861. //
  862. NewDevice->StackSize = NewExtension->CommonExtension.AttachedDevice->StackSize + 1;
  863. NewDevice->AlignmentRequirement = NewExtension->CommonExtension.AttachedDevice->AlignmentRequirement;
  864. if (NewExtension->CommonExtension.AttachedDevice->Flags & DO_POWER_PAGABLE) {
  865. NewDevice->Flags |= DO_POWER_PAGABLE;
  866. }
  867. //
  868. // Finally call the chipset-specific code for master initialization
  869. //
  870. routineContext.Gate = 1;
  871. routineContext.Barrier = 1;
  872. routineContext.Routine = (PCRITICALROUTINE)AgpInitializeMaster;
  873. routineContext.Extension = GET_AGP_CONTEXT(Extension);
  874. routineContext.Context = &NewExtension->Capabilities;
  875. #if (WINVER < 0x502) || defined(AGP_DEBUG_MASTER_INIT)
  876. Status = AgpInitializeMaster(GET_AGP_CONTEXT(Extension),
  877. &NewExtension->Capabilities);
  878. #else
  879. Status = (NTSTATUS)KeIpiGenericCall(AgpExecuteCriticalSystemRoutine,
  880. (ULONG_PTR)&routineContext
  881. );
  882. #endif
  883. if (!NT_SUCCESS(Status)) {
  884. AGPLOG(AGP_CRITICAL,
  885. ("AgpAttachDeviceRelations: AgpInitializeMaster on device %08lx failed %08lx\n",
  886. NewDevice,
  887. Status));
  888. IoDetachDevice(NewExtension->CommonExtension.AttachedDevice);
  889. RELEASE_BUS_INTERFACE(NewExtension);
  890. IoDeleteDevice(NewDevice);
  891. Extension->ChildDevice = NULL;
  892. continue;
  893. }
  894. NewDevice->Flags &= ~DO_DEVICE_INITIALIZING;
  895. //
  896. // We can't do this if DBG because looping through here to catch/ASSERT
  897. // multiple AGP masters will *always* screw up our target context
  898. //
  899. #if 0
  900. //
  901. // Check to make sure there is only one AGP master on the bus. There can be more
  902. // than one device (multifunction device) but only one must have AGP capabilities
  903. //
  904. MasterCount++;
  905. ASSERT(MasterCount == 1);
  906. #else
  907. break;
  908. #endif
  909. }
  910. return(STATUS_SUCCESS);
  911. }