Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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