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.

3004 lines
92 KiB

  1. //***************************************************************************
  2. //
  3. // Module Name:
  4. //
  5. // permedia.c
  6. //
  7. // Abstract:
  8. //
  9. // This module contains the code that implements the Permedia2 miniport driver
  10. //
  11. // Environment:
  12. //
  13. // Kernel mode
  14. //
  15. //
  16. // Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  17. // Copyright (c) 1995-1999 Microsoft Corporation. All Rights Reserved.
  18. //
  19. //***************************************************************************
  20. #include "permedia.h"
  21. #include "string.h"
  22. #define USE_SINGLE_CYCLE_BLOCK_WRITES 0
  23. #if defined(ALLOC_PRAGMA)
  24. #pragma alloc_text(PAGE,DriverEntry)
  25. #pragma alloc_text(PAGE,Permedia2FindAdapter)
  26. #pragma alloc_text(PAGE,Permedia2RegistryCallback)
  27. #pragma alloc_text(PAGE,Permedia2RetrieveGammaCallback)
  28. #pragma alloc_text(PAGE,InitializeAndSizeRAM)
  29. #pragma alloc_text(PAGE,ConstructValidModesList)
  30. #pragma alloc_text(PAGE,Permedia2Initialize)
  31. #pragma alloc_text(PAGE,Permedia2StartIO)
  32. #pragma alloc_text(PAGE,Permedia2SetColorLookup)
  33. #pragma alloc_text(PAGE,Permedia2GetClockSpeeds)
  34. #pragma alloc_text(PAGE,ZeroMemAndDac)
  35. #endif
  36. //
  37. // NtVersion: NT4 - This driver is working on NT4
  38. // WIN2K - This driver is working on Windows 2000
  39. //
  40. short NtVersion;
  41. ULONG
  42. DriverEntry (
  43. PVOID Context1,
  44. PVOID Context2
  45. )
  46. /*++
  47. Routine Description:
  48. This routine is the initial entry point to the video miniport driver.
  49. This routine is called by the I/O subsystem when the video miniport
  50. is loaded. The miniport is responsible for initializing a
  51. VIDEO_HW_INITIALIZATION_DATA structure to register the driver functions
  52. called by the video port driver in response to requests from the display
  53. driver, plug and play manager, power management, or other driver
  54. components.
  55. The following tasks MUST be completed by the video miniport in the
  56. context of DriverEntry. Driver writers should consult the documentation
  57. for full details on the exact initialization process.
  58. 1. Initialize VIDEO_HW_INITIALIZATION_DATA structure with all relevant
  59. data structures.
  60. 2. Call VideoPortInitialize.
  61. 3. Return appropriate status value to the caller of DriverEntry.
  62. Drivers can undertake other tasks as required and under the restrictions
  63. outlined in the documentation.
  64. Arguments:
  65. Context1 - First context value passed by the operating system. This is
  66. the value with which the miniport driver calls VideoPortInitialize().
  67. Context2 - Second context value passed by the operating system. This is
  68. the value with which the miniport driver calls VideoPortInitialize().
  69. Return Value:
  70. Status from VideoPortInitialize()
  71. --*/
  72. {
  73. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  74. VP_STATUS initializationStatus;
  75. //
  76. // Zero out structure.
  77. //
  78. VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
  79. //
  80. // Specify sizes of structure and extension.
  81. //
  82. hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
  83. //
  84. // Set entry points.
  85. //
  86. hwInitData.HwFindAdapter = Permedia2FindAdapter;
  87. hwInitData.HwInitialize = Permedia2Initialize;
  88. hwInitData.HwStartIO = Permedia2StartIO;
  89. hwInitData.HwResetHw = Permedia2ResetHW;
  90. hwInitData.HwInterrupt = Permedia2VidInterrupt;
  91. hwInitData.HwGetPowerState = Permedia2GetPowerState;
  92. hwInitData.HwSetPowerState = Permedia2SetPowerState;
  93. hwInitData.HwGetVideoChildDescriptor = Permedia2GetChildDescriptor;
  94. //
  95. // Declare the legacy resources
  96. //
  97. hwInitData.HwLegacyResourceList = P2LegacyResourceList;
  98. hwInitData.HwLegacyResourceCount = P2LegacyResourceEntries;
  99. //
  100. // Determine the size we require for the device extension.
  101. //
  102. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  103. //
  104. // This device only supports the PCI bus.
  105. //
  106. hwInitData.AdapterInterfaceType = PCIBus;
  107. NtVersion = WIN2K;
  108. initializationStatus = VideoPortInitialize(Context1,
  109. Context2,
  110. &hwInitData,
  111. NULL);
  112. if( initializationStatus != NO_ERROR)
  113. {
  114. hwInitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
  115. initializationStatus = VideoPortInitialize(Context1,
  116. Context2,
  117. &hwInitData,
  118. NULL);
  119. }
  120. if( initializationStatus != NO_ERROR)
  121. {
  122. NtVersion = NT4;
  123. hwInitData.HwInterrupt = NULL;
  124. hwInitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
  125. initializationStatus = VideoPortInitialize(Context1,
  126. Context2,
  127. &hwInitData,
  128. NULL);
  129. }
  130. DEBUG_PRINT((2, "PERM2: VideoPortInitialize returned status 0x%x\n", initializationStatus));
  131. return initializationStatus;
  132. } // end DriverEntry()
  133. VP_STATUS
  134. Permedia2FindAdapter(
  135. PVOID HwDeviceExtension,
  136. PVOID pReserved,
  137. PWSTR ArgumentString,
  138. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  139. PUCHAR Again
  140. )
  141. /*++
  142. Routine Description:
  143. This routine gets the access ranges for a device on an enumerable
  144. bus and, if necessary, determines the device type
  145. Arguments:
  146. HwDeviceExtension -
  147. System supplied device extension supplied to the miniport for
  148. a per-device storage area.
  149. pReserved -
  150. NULL on Windows 2000 and should be ignored by the miniport.
  151. ArgumentString -
  152. Suuplies a NULL terminated ASCII string. This string originates
  153. from the user. This pointer can be NULL.
  154. ConfigInfo -
  155. Points to a VIDEO_PORT_CONFIG_INFO structure allocated and initialized
  156. by the port driver. This structure will contain as much information
  157. as could be obtained by the port driver. This routine is responsible
  158. for filling in any relevant missing information.
  159. Again - Is not used on Windows 2000.
  160. We set this to FALSE on NT 4, since we only support one adapter on NT4.
  161. Return Value:
  162. This routine must return:
  163. NO_ERROR -
  164. Indicates that the routine completed without error.
  165. ERROR_INVALID_PARAMETER -
  166. Indicates that the adapter could not be properly configured or
  167. information was inconsistent. (NOTE: This does not mean that the
  168. adapter could not be initialized. Miniports must not attempt to
  169. initialize the adapter until HwVidInitialize.)
  170. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
  171. supplied configuration information.
  172. --*/
  173. {
  174. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  175. P2_DECL_VARS;
  176. WCHAR StringBuffer[60];
  177. ULONG StringLength;
  178. VP_STATUS vpStatus;
  179. ULONG UseSoftwareCursor;
  180. ULONG ulValue;
  181. ULONG i;
  182. VIDEO_ACCESS_RANGE *pciAccessRange = hwDeviceExtension->PciAccessRange;
  183. PWSTR pwszChip, pwszDAC, pwszAdapterString;
  184. ULONG cbChip, cbDAC, cbAdapterString, cbBiosString;
  185. ULONG pointerCaps;
  186. USHORT usData;
  187. //
  188. // 3 (major number) + 1 (dot) + 3 (minor number) + 1 (L'\0') = 8 digtis
  189. // is enough for bios verions string
  190. //
  191. WCHAR pwszBiosString[8];
  192. //
  193. // save current NT version obtained at DriverEntry
  194. //
  195. hwDeviceExtension->NtVersion = NtVersion;
  196. //
  197. // Make sure the size of the structure is at least as large as what we
  198. // are expecting (check version of the config info structure).
  199. //
  200. if ( (NtVersion == WIN2K) &&
  201. (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) )
  202. {
  203. DEBUG_PRINT((1, "bad size for VIDEO_PORT_CONFIG_INFO\n"));
  204. return (ERROR_INVALID_PARAMETER);
  205. }
  206. else if ( (NtVersion == NT4) &&
  207. (ConfigInfo->Length < SIZE_OF_NT4_VIDEO_PORT_CONFIG_INFO) )
  208. {
  209. DEBUG_PRINT((1, "bad size for VIDEO_PORT_CONFIG_INFO\n"));
  210. return (ERROR_INVALID_PARAMETER);
  211. }
  212. //
  213. // we must be a PCI device
  214. //
  215. if (ConfigInfo->AdapterInterfaceType != PCIBus)
  216. {
  217. DEBUG_PRINT((1, "not a PCI device\n"));
  218. return (ERROR_DEV_NOT_EXIST);
  219. }
  220. //
  221. // Retrieve pointers of those new video port functions in Win2k.
  222. // If you don't want to support NT4, you don't need to do this. You
  223. // can just call these functions by their name.
  224. //
  225. if ( NtVersion == WIN2K )
  226. {
  227. if(!(hwDeviceExtension->Win2kVideoPortGetRomImage =
  228. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  229. "VideoPortGetRomImage")))
  230. {
  231. return (ERROR_DEV_NOT_EXIST);
  232. }
  233. if(!(hwDeviceExtension->Win2kVideoPortGetCommonBuffer =
  234. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  235. "VideoPortGetCommonBuffer")))
  236. {
  237. return (ERROR_DEV_NOT_EXIST);
  238. }
  239. if(!(hwDeviceExtension->Win2kVideoPortFreeCommonBuffer =
  240. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  241. "VideoPortFreeCommonBuffer")))
  242. {
  243. return (ERROR_DEV_NOT_EXIST);
  244. }
  245. if(!(hwDeviceExtension->Win2kVideoPortDDCMonitorHelper =
  246. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  247. "VideoPortDDCMonitorHelper")))
  248. {
  249. return (ERROR_DEV_NOT_EXIST);
  250. }
  251. if(!(hwDeviceExtension->Win2kVideoPortInterlockedExchange =
  252. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  253. "VideoPortInterlockedExchange")))
  254. {
  255. return (ERROR_DEV_NOT_EXIST);
  256. }
  257. if(!(hwDeviceExtension->Win2kVideoPortGetVgaStatus =
  258. ConfigInfo->VideoPortGetProcAddress( hwDeviceExtension,
  259. "VideoPortGetVgaStatus")))
  260. {
  261. return (ERROR_DEV_NOT_EXIST);
  262. }
  263. }
  264. else
  265. {
  266. //
  267. // We only support one adapter on NT 4
  268. //
  269. Again = FALSE;
  270. }
  271. //
  272. // will be initialized in CopyROMInitializationTable
  273. //
  274. hwDeviceExtension->culTableEntries = 0;
  275. //
  276. // will be initialized in ConstructValidModesList
  277. //
  278. hwDeviceExtension->pFrequencyDefault = NULL;
  279. //
  280. // We'll set this TRUE when in InitializeVideo after programming the VTG
  281. //
  282. hwDeviceExtension->bVTGRunning = FALSE;
  283. hwDeviceExtension->bMonitorPoweredOn = TRUE;
  284. hwDeviceExtension->ChipClockSpeed = 0;
  285. hwDeviceExtension->RefClockSpeed = 0;
  286. hwDeviceExtension->P28bppRGB = 0;
  287. hwDeviceExtension->ExportNon3DModes = 0;
  288. hwDeviceExtension->PreviousPowerState = VideoPowerOn;
  289. //
  290. // pick up capabilities on the way.
  291. //
  292. hwDeviceExtension->Capabilities = CAPS_GLYPH_EXPAND;
  293. //
  294. // We'll use a software pointer in all modes if the user sets
  295. // the correct entry in the registry.
  296. //
  297. UseSoftwareCursor = 0;
  298. vpStatus = VideoPortGetRegistryParameters( HwDeviceExtension,
  299. L"UseSoftwareCursor",
  300. FALSE,
  301. Permedia2RegistryCallback,
  302. &UseSoftwareCursor);
  303. if ( ( vpStatus == NO_ERROR ) && UseSoftwareCursor)
  304. {
  305. hwDeviceExtension->Capabilities |= CAPS_SW_POINTER;
  306. }
  307. //
  308. // Query the PCI to see if any of our supported chip devices exist.
  309. //
  310. if ( NtVersion == WIN2K )
  311. {
  312. if (!Permedia2AssignResources( HwDeviceExtension,
  313. ConfigInfo,
  314. PCI_TYPE0_ADDRESSES + 1,
  315. pciAccessRange ))
  316. {
  317. DEBUG_PRINT((1, "Permedia2AssignResources failed\n"));
  318. return (ERROR_DEV_NOT_EXIST);
  319. }
  320. }
  321. else
  322. {
  323. if (!Permedia2AssignResourcesNT4( HwDeviceExtension,
  324. ConfigInfo,
  325. PCI_TYPE0_ADDRESSES + 1,
  326. pciAccessRange ))
  327. {
  328. DEBUG_PRINT((1, "Permedia2AssignResources failed\n"));
  329. return (ERROR_DEV_NOT_EXIST);
  330. }
  331. }
  332. //
  333. // construct the identifier string including the revision id
  334. //
  335. StringLength = sizeof(L"3Dlabs PERMEDIA2");
  336. VideoPortMoveMemory((PVOID)StringBuffer,
  337. (PVOID)(L"3Dlabs PERMEDIA2"),
  338. StringLength);
  339. pwszChip = (PWSTR)StringBuffer;
  340. cbChip = StringLength;
  341. //
  342. // Set the defaults for the board type.
  343. //
  344. hwDeviceExtension->deviceInfo.BoardId = PERMEDIA2_BOARD;
  345. pwszAdapterString = L"Permedia 2";
  346. cbAdapterString = sizeof(L"Permedia 2");
  347. //
  348. // Get the mapped addresses for the control registers and the
  349. // framebuffer. Must use local variable pCtrlRegs so macro
  350. // declarations further down will work.
  351. //
  352. pCtrlRegs = VideoPortGetDeviceBase(
  353. HwDeviceExtension,
  354. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeStart,
  355. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeLength,
  356. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeInIoSpace
  357. );
  358. if (pCtrlRegs == NULL)
  359. {
  360. DEBUG_PRINT((1, "CTRL DeviceBase mapping failed\n"));
  361. return ERROR_INVALID_PARAMETER;
  362. }
  363. hwDeviceExtension->ctrlRegBase = pCtrlRegs;
  364. //
  365. // Some boards have a ROM which we can use to identify them.
  366. //
  367. CopyROMInitializationTable(hwDeviceExtension);
  368. if(hwDeviceExtension->culTableEntries == 0)
  369. {
  370. //
  371. // No initialization table, but P2 really needs one in order to come
  372. // out of sleep mode correctly. Generate initialization table by
  373. // default values
  374. //
  375. GenerateInitializationTable(hwDeviceExtension);
  376. }
  377. //
  378. // Find out what type of RAMDAC we have.
  379. //
  380. vpStatus = NO_ERROR;
  381. hwDeviceExtension->pRamdac = &(pCtrlRegs->ExternalVideo);
  382. //
  383. // some RAMDACs may not support a cursor so a software cursor is the default
  384. //
  385. pointerCaps = CAPS_SW_POINTER;
  386. //
  387. // Check for a TI TVP4020
  388. //
  389. if(DEVICE_FAMILY_ID(hwDeviceExtension->deviceInfo.DeviceId) == PERMEDIA_P2S_ID)
  390. {
  391. //
  392. // P2 with 3Dlabs RAMDAC, check for a rev 2 chip
  393. //
  394. i = VideoPortReadRegisterUlong(CHIP_CONFIG);
  395. if(i & 0x40000000)
  396. {
  397. DEBUG_PRINT((2, "PERM2: Permedia2 is rev 2\n"));
  398. hwDeviceExtension->deviceInfo.RevisionId = 2;
  399. }
  400. else
  401. {
  402. DEBUG_PRINT((2, "PERM2: Permedia2 is rev 1\n"));
  403. }
  404. hwDeviceExtension->DacId = P2RD_RAMDAC;
  405. pointerCaps = (ULONG)CAPS_P2RD_POINTER;
  406. hwDeviceExtension->deviceInfo.ActualDacId = P2RD_RAMDAC;
  407. pwszDAC = L"3Dlabs P2RD";
  408. cbDAC = sizeof(L"3Dlabs P2RD");
  409. DEBUG_PRINT((1, "PERM2: using P2RD RAMDAC\n"));
  410. }
  411. else
  412. {
  413. hwDeviceExtension->DacId = TVP4020_RAMDAC;
  414. pointerCaps = CAPS_TVP4020_POINTER;
  415. hwDeviceExtension->deviceInfo.ActualDacId = TVP4020_RAMDAC;
  416. if(hwDeviceExtension->deviceInfo.RevisionId == PERMEDIA2A_REV_ID)
  417. {
  418. pwszDAC = L"TI TVP4020A";
  419. cbDAC = sizeof(L"TI TVP4020A");
  420. DEBUG_PRINT((1, "PERM2: using TVP4020A RAMDAC\n"));
  421. }
  422. else
  423. {
  424. pwszDAC = L"TI TVP4020C";
  425. cbDAC = sizeof(L"TI TVP4020C");
  426. DEBUG_PRINT((1, "PERM2: using TVP4020C RAMDAC\n"));
  427. }
  428. }
  429. //
  430. // use the RAMDAC cursor capability only if the user didn't specify
  431. // a software cursor
  432. //
  433. if (!(hwDeviceExtension->Capabilities & CAPS_SW_POINTER))
  434. {
  435. hwDeviceExtension->Capabilities |= pointerCaps;
  436. }
  437. hwDeviceExtension->PhysicalFrameIoSpace =
  438. pciAccessRange[PCI_FB_BASE_INDEX].RangeInIoSpace |
  439. VIDEO_MEMORY_SPACE_P6CACHE;
  440. if ( (hwDeviceExtension->pFramebuffer =
  441. VideoPortGetDeviceBase(
  442. HwDeviceExtension,
  443. pciAccessRange[PCI_FB_BASE_INDEX].RangeStart,
  444. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength,
  445. (UCHAR) hwDeviceExtension->PhysicalFrameIoSpace
  446. ) ) == NULL)
  447. {
  448. //
  449. // Some machines have limitations on how much PCI address space they
  450. // can map in so try again, reducing the amount we map till we succeed
  451. // or the size gets to zero in which case we really have failed.
  452. //
  453. ULONG sz;
  454. DEBUG_PRINT((1, "PERM2: FB DeviceBase mapping failed\n"));
  455. for ( sz = pciAccessRange[PCI_FB_BASE_INDEX].RangeLength;
  456. sz > 0;
  457. sz -= 1024*1024 )
  458. {
  459. if ( (hwDeviceExtension->pFramebuffer =
  460. VideoPortGetDeviceBase(
  461. HwDeviceExtension,
  462. pciAccessRange[PCI_FB_BASE_INDEX].RangeStart,
  463. sz,
  464. (UCHAR) hwDeviceExtension->PhysicalFrameIoSpace
  465. ) ) != NULL)
  466. {
  467. //
  468. // store the modified size
  469. //
  470. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength = sz;
  471. break;
  472. }
  473. }
  474. //
  475. // if sz is zero, well we tried ...
  476. //
  477. if (sz == 0)
  478. return ERROR_INVALID_PARAMETER;
  479. }
  480. DEBUG_PRINT((1, "PERM2: FB mapped at 0x%x for length 0x%x (%s)\n",
  481. hwDeviceExtension->pFramebuffer,
  482. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength,
  483. pciAccessRange[PCI_FB_BASE_INDEX].RangeInIoSpace ?
  484. "I/O Ports" : "MemMapped"));
  485. //
  486. // Initialize the RAM registers and dynamically size the framebuffer
  487. //
  488. if (!InitializeAndSizeRAM(hwDeviceExtension, pciAccessRange))
  489. {
  490. DEBUG_PRINT((0, "InitializeAndSizeRAM failed\n"));
  491. return ERROR_DEV_NOT_EXIST;
  492. }
  493. //
  494. // Record the size of the video memory.
  495. //
  496. hwDeviceExtension->AdapterMemorySize =
  497. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength;
  498. #if defined(_ALPHA_)
  499. //
  500. // We want to use a dense space mapping of the frame buffer
  501. // whenever we can on the Alpha.
  502. //
  503. hwDeviceExtension->PhysicalFrameIoSpace = 4;
  504. //
  505. // The new DeskStation Alpha machines don't always support
  506. // dense space. Therefore, we should try to map the memory
  507. // at this point as a test. If the mapping succeeds then
  508. // we can use dense space, otherwise we'll use sparse space.
  509. //
  510. {
  511. PULONG MappedSpace=0;
  512. VP_STATUS status;
  513. DEBUG_PRINT((1, "PERM2: Checking to see if we can use dense space...\n"));
  514. //
  515. // We want to try to map the dense memory where it will ultimately
  516. // be mapped anyway.
  517. //
  518. MappedSpace = (PULONG)VideoPortGetDeviceBase (
  519. hwDeviceExtension,
  520. pciAccessRange[PCI_FB_BASE_INDEX].RangeStart,
  521. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength,
  522. (UCHAR) hwDeviceExtension->PhysicalFrameIoSpace
  523. );
  524. if (MappedSpace == NULL)
  525. {
  526. //
  527. // Well, looks like we can't use dense space to map the
  528. // range. Lets use sparse space, and let the display
  529. // driver know.
  530. //
  531. DEBUG_PRINT((1, "PERM2: Can't use dense space!\n"));
  532. hwDeviceExtension->PhysicalFrameIoSpace = 0;
  533. hwDeviceExtension->Capabilities |= CAPS_SPARSE_SPACE;
  534. }
  535. else
  536. {
  537. //
  538. // The mapping worked. However, we were only mapping to
  539. // see if dense space was supported. Free the memory.
  540. //
  541. DEBUG_PRINT((1, "PERM2: We can use dense space.\n"));
  542. VideoPortFreeDeviceBase(hwDeviceExtension,
  543. MappedSpace);
  544. }
  545. }
  546. #endif // defined(_ALPHA_)
  547. //
  548. // We now have a complete hardware description of the hardware.
  549. // Save the information to the registry so it can be used by
  550. // configuration programs - such as the display applet.
  551. //
  552. VideoPortSetRegistryParameters(HwDeviceExtension,
  553. L"HardwareInformation.ChipType",
  554. pwszChip,
  555. cbChip);
  556. VideoPortSetRegistryParameters(HwDeviceExtension,
  557. L"HardwareInformation.DacType",
  558. pwszDAC,
  559. cbDAC);
  560. VideoPortSetRegistryParameters(HwDeviceExtension,
  561. L"HardwareInformation.MemorySize",
  562. &hwDeviceExtension->AdapterMemorySize,
  563. sizeof(ULONG));
  564. VideoPortSetRegistryParameters(HwDeviceExtension,
  565. L"HardwareInformation.AdapterString",
  566. pwszAdapterString,
  567. cbAdapterString);
  568. cbBiosString = GetBiosVersion(HwDeviceExtension, (PWSTR) pwszBiosString);
  569. VideoPortSetRegistryParameters(HwDeviceExtension,
  570. L"HardwareInformation.BiosString",
  571. pwszBiosString,
  572. cbBiosString);
  573. ConstructValidModesList(HwDeviceExtension, hwDeviceExtension);
  574. if (hwDeviceExtension->NumAvailableModes == 0)
  575. {
  576. DEBUG_PRINT((1, "No video modes available\n"));
  577. return(ERROR_DEV_NOT_EXIST);
  578. }
  579. //
  580. // Frame buffer information
  581. //
  582. hwDeviceExtension->PhysicalFrameAddress =
  583. pciAccessRange[PCI_FB_BASE_INDEX].RangeStart;
  584. hwDeviceExtension->FrameLength =
  585. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength;
  586. //
  587. // Control Register information
  588. // Get the base address, starting at zero and map all registers
  589. //
  590. hwDeviceExtension->PhysicalRegisterAddress =
  591. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeStart;
  592. hwDeviceExtension->RegisterLength =
  593. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeLength;
  594. hwDeviceExtension->RegisterSpace =
  595. pciAccessRange[PCI_CTRL_BASE_INDEX].RangeInIoSpace;
  596. ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000;
  597. ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
  598. ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000;
  599. //
  600. // Clear out the Emulator entries and the state size since this driver
  601. // does not support them.
  602. //
  603. ConfigInfo->NumEmulatorAccessEntries = 0;
  604. ConfigInfo->EmulatorAccessEntries = NULL;
  605. ConfigInfo->EmulatorAccessEntriesContext = 0;
  606. //
  607. // This driver does not do SAVE/RESTORE of hardware state.
  608. //
  609. ConfigInfo->HardwareStateSize = 0;
  610. //
  611. // in a multi-adapter system we'll need to disable VGA for the
  612. // secondary adapters
  613. //
  614. if(!hwDeviceExtension->bVGAEnabled)
  615. {
  616. DEBUG_PRINT((1, "PERM2: disabling VGA for the secondary card\n"));
  617. //
  618. // Enable graphics mode, disable VGA
  619. //
  620. VideoPortWriteRegisterUchar(PERMEDIA_MMVGA_INDEX_REG,
  621. PERMEDIA_VGA_CTRL_INDEX);
  622. usData = (USHORT)VideoPortReadRegisterUchar(PERMEDIA_MMVGA_DATA_REG);
  623. usData &= ~PERMEDIA_VGA_ENABLE;
  624. usData = (usData << 8) | PERMEDIA_VGA_CTRL_INDEX;
  625. VideoPortWriteRegisterUshort(PERMEDIA_MMVGA_INDEX_REG, usData);
  626. #define INTERNAL_VGA_ENABLE (1 << 1)
  627. #define VGA_FIXED_ADD_DECODE (1 << 2)
  628. ulValue = VideoPortReadRegisterUlong(CHIP_CONFIG);
  629. ulValue &= ~INTERNAL_VGA_ENABLE;
  630. ulValue &= ~VGA_FIXED_ADD_DECODE;
  631. VideoPortWriteRegisterUlong(CHIP_CONFIG, ulValue);
  632. }
  633. //
  634. // Indicate a successful completion status.
  635. //
  636. return NO_ERROR;
  637. } // end Permedia2FindAdapter()
  638. VOID
  639. ConstructValidModesList(
  640. PVOID HwDeviceExtension,
  641. PHW_DEVICE_EXTENSION hwDeviceExtension
  642. )
  643. /*++
  644. Routine Description:
  645. Here we prune valid modes, based on rules according to the chip
  646. capabilities and memory requirements.
  647. We prune modes so that we will not annoy the user by presenting
  648. modes in the 'Video Applet' which we know the user can't use.
  649. Look up the registry to see if we want to export modes which can only
  650. be used as single buffered by 3D applications. If we only want double
  651. buffered modes then, effectively, we have only half the memory in
  652. which to display the standard 2D resolution. This is only not true at 12bpp
  653. where we can double buffer at any resolution.
  654. --*/
  655. {
  656. PP2_VIDEO_FREQUENCIES FrequencyEntry;
  657. PP2_VIDEO_MODES ModeEntry;
  658. LONG AdapterMemorySize;
  659. ULONG ModeIndex;
  660. ULONG i;
  661. hwDeviceExtension->NumAvailableModes = 0;
  662. //
  663. // Since there are a number of frequencies possible for each
  664. // distinct resolution/colour depth, we cycle through the
  665. // frequency table and find the appropriate mode entry for that
  666. // frequency entry.
  667. //
  668. if (!BuildFrequencyList(hwDeviceExtension))
  669. return;
  670. for (FrequencyEntry = hwDeviceExtension->FrequencyTable, ModeIndex = 0;
  671. FrequencyEntry->BitsPerPel != 0;
  672. FrequencyEntry++, ModeIndex++)
  673. {
  674. //
  675. // Find the mode for this entry. First, assume we won't find one.
  676. //
  677. FrequencyEntry->ModeValid = FALSE;
  678. FrequencyEntry->ModeIndex = ModeIndex;
  679. for (ModeEntry = P2Modes, i = 0; i < NumP2VideoModes; ModeEntry++, i++)
  680. {
  681. if ((FrequencyEntry->BitsPerPel ==
  682. ModeEntry->ModeInformation.BitsPerPlane) &&
  683. (FrequencyEntry->ScreenWidth ==
  684. ModeEntry->ModeInformation.VisScreenWidth) &&
  685. (FrequencyEntry->ScreenHeight ==
  686. ModeEntry->ModeInformation.VisScreenHeight))
  687. {
  688. AdapterMemorySize = (LONG)hwDeviceExtension->AdapterMemorySize;
  689. //
  690. // We've found a mode table entry that matches this frequency
  691. // table entry. Now we'll figure out if we can actually do
  692. // this mode/frequency combination. For now, assume we'll
  693. // succeed.
  694. //
  695. FrequencyEntry->ModeEntry = ModeEntry;
  696. FrequencyEntry->ModeValid = TRUE;
  697. ModeEntry->ModeInformation.ScreenStride =
  698. ModeEntry->ScreenStrideContiguous;
  699. //
  700. // Rule: use true color at 8bpp if we've enabled that
  701. // capability above.
  702. //
  703. if ((FrequencyEntry->BitsPerPel == 8) &&
  704. (hwDeviceExtension->Capabilities & CAPS_8BPP_RGB))
  705. {
  706. ModeEntry->ModeInformation.AttributeFlags &=
  707. ~(VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE);
  708. //
  709. // NB. These must match the way the palette is loaded in
  710. // InitializeVideo.
  711. //
  712. ModeEntry->ModeInformation.RedMask = 0x07;
  713. ModeEntry->ModeInformation.GreenMask = 0x38;
  714. ModeEntry->ModeInformation.BlueMask = 0xc0;
  715. }
  716. //
  717. // Rule: We have to have enough memory to handle the mode.
  718. //
  719. if ((LONG)(ModeEntry->ModeInformation.VisScreenHeight *
  720. ModeEntry->ModeInformation.ScreenStride) >
  721. AdapterMemorySize)
  722. {
  723. FrequencyEntry->ModeValid = FALSE;
  724. }
  725. {
  726. ULONG pixelData;
  727. ULONG DacDepth = FrequencyEntry->BitsPerPel;
  728. //
  729. // We need the proper pixel size to calculate timing values
  730. //
  731. if (DacDepth == 15)
  732. {
  733. DacDepth = 16;
  734. }
  735. else if (DacDepth == 12)
  736. {
  737. DacDepth = 32;
  738. }
  739. pixelData = FrequencyEntry->PixelClock * (DacDepth / 8);
  740. if (((FrequencyEntry->PixelClock > P2_MAX_PIXELCLOCK ||
  741. pixelData > P2_MAX_PIXELDATA)))
  742. {
  743. FrequencyEntry->ModeValid = FALSE;
  744. }
  745. //
  746. // Don't supports 24bpp
  747. //
  748. if(FrequencyEntry->BitsPerPel == 24)
  749. {
  750. FrequencyEntry->ModeValid = FALSE;
  751. }
  752. }
  753. //
  754. // Don't forget to count it if it's still a valid mode after
  755. // applying all those rules.
  756. //
  757. if (FrequencyEntry->ModeValid)
  758. {
  759. if(hwDeviceExtension->pFrequencyDefault == NULL &&
  760. ModeEntry->ModeInformation.BitsPerPlane == 8 &&
  761. ModeEntry->ModeInformation.VisScreenWidth == 640 &&
  762. ModeEntry->ModeInformation.VisScreenHeight == 480)
  763. {
  764. hwDeviceExtension->pFrequencyDefault = FrequencyEntry;
  765. }
  766. hwDeviceExtension->NumAvailableModes++;
  767. }
  768. //
  769. // We've found a mode for this frequency entry, so we
  770. // can break out of the mode loop:
  771. //
  772. break;
  773. }
  774. }
  775. }
  776. hwDeviceExtension->NumTotalModes = ModeIndex;
  777. DEBUG_PRINT((2, "PERM2: %d total modes\n", ModeIndex));
  778. DEBUG_PRINT((2, "PERM2: %d total valid modes\n", hwDeviceExtension->NumAvailableModes));
  779. }
  780. VP_STATUS
  781. Permedia2RegistryCallback(
  782. PVOID HwDeviceExtension,
  783. PVOID Context,
  784. PWSTR ValueName,
  785. PVOID ValueData,
  786. ULONG ValueLength
  787. )
  788. /*++
  789. Routine Description:
  790. This routine is used to read back various registry values.
  791. Arguments:
  792. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  793. Context - Context value passed to the get registry paramters routine. If
  794. this is not null assume it's a ULONG* and save the data value in it.
  795. ValueName - Name of the value requested.
  796. ValueData - Pointer to the requested data.
  797. ValueLength - Length of the requested data.
  798. Return Value:
  799. if the variable doesn't exist return an error,
  800. else if a context is supplied assume it's a PULONG and fill in the value
  801. and return no error, else if the value is non-zero return an error.
  802. --*/
  803. {
  804. if (ValueLength)
  805. {
  806. if (Context)
  807. {
  808. *(ULONG *)Context = *(PULONG)ValueData;
  809. }
  810. else if (*((PULONG)ValueData) != 0)
  811. {
  812. return ERROR_INVALID_PARAMETER;
  813. }
  814. return NO_ERROR;
  815. } else
  816. {
  817. return ERROR_INVALID_PARAMETER;
  818. }
  819. } // end Permedia2RegistryCallback()
  820. VP_STATUS
  821. Permedia2RetrieveGammaCallback(
  822. PVOID HwDeviceExtension,
  823. PVOID Context,
  824. PWSTR ValueName,
  825. PVOID ValueData,
  826. ULONG ValueLength
  827. )
  828. /*++
  829. Routine Description:
  830. This routine is used to read back the gamma LUT from the registry.
  831. Arguments:
  832. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  833. Context - Context value passed to the get registry paramters routine
  834. ValueName - Name of the value requested.
  835. ValueData - Pointer to the requested data.
  836. ValueLength - Length of the requested data.
  837. Return Value:
  838. if the variable doesn't exist return an error, else copy the gamma lut
  839. into the supplied pointer
  840. --*/
  841. {
  842. if (ValueLength != MAX_CLUT_SIZE)
  843. {
  844. DEBUG_PRINT((1, "Permedia2RetrieveGammaCallback got ValueLength of %d\n", ValueLength));
  845. return ERROR_INVALID_PARAMETER;
  846. }
  847. VideoPortMoveMemory(Context, ValueData, MAX_CLUT_SIZE);
  848. return NO_ERROR;
  849. } // end Permedia2RetrieveGammaCallback()
  850. BOOLEAN
  851. InitializeAndSizeRAM(
  852. PHW_DEVICE_EXTENSION hwDeviceExtension,
  853. PVIDEO_ACCESS_RANGE pciAccessRange
  854. )
  855. /*++
  856. Routine Description:
  857. Initialize extra control registers and dynamically size the
  858. video RAM for the Permedia.
  859. Arguments:
  860. hwDeviceExtension - Supplies a pointer to the miniport's device extension.
  861. pciAccessRange - access range of mapped resources
  862. Return Value:
  863. FALSE if we find no RAM, TRUE otherwise
  864. --*/
  865. {
  866. PVOID HwDeviceExtension = (PVOID)hwDeviceExtension;
  867. ULONG fbMappedSize;
  868. ULONG i, j;
  869. P2_DECL;
  870. PULONG pV, pVStart, pVEnd;
  871. ULONG testPattern;
  872. ULONG probeSize;
  873. ULONG save0, save1;
  874. ULONG temp;
  875. ULONG saveVidCtl;
  876. USHORT saveVGA, usData;
  877. if(hwDeviceExtension->culTableEntries)
  878. {
  879. //
  880. // When vga is enabled, these registers should be set by bios at
  881. // boot time. But we saw cases when bios failed to do this. We'll
  882. // set these register when vga is off or when we see values are
  883. // wrong
  884. //
  885. if(!hwDeviceExtension->bVGAEnabled ||
  886. !VerifyBiosSettings(hwDeviceExtension))
  887. {
  888. //
  889. // save video control and vga register
  890. //
  891. saveVidCtl = VideoPortReadRegisterUlong(VIDEO_CONTROL);
  892. VideoPortWriteRegisterUchar( PERMEDIA_MMVGA_INDEX_REG,
  893. PERMEDIA_VGA_CTRL_INDEX );
  894. saveVGA = (USHORT)VideoPortReadRegisterUchar(
  895. PERMEDIA_MMVGA_DATA_REG );
  896. //
  897. // Disable Video and VGA
  898. //
  899. VideoPortWriteRegisterUlong(VIDEO_CONTROL, 0);
  900. usData = saveVGA & (USHORT)(~PERMEDIA_VGA_ENABLE);
  901. usData = (usData << 8) | PERMEDIA_VGA_CTRL_INDEX;
  902. VideoPortWriteRegisterUshort(PERMEDIA_MMVGA_INDEX_REG, usData);
  903. ProcessInitializationTable(hwDeviceExtension);
  904. #if USE_SINGLE_CYCLE_BLOCK_WRITES
  905. {
  906. i = VideoPortReadRegisterUlong(MEM_CONFIG);
  907. VideoPortWriteRegisterUlong(MEM_CONFIG, i | (1 << 21)); // single cycle block writes
  908. }
  909. #endif //USE_SINGLE_CYCLE_BLOCK_WRITES
  910. //
  911. // Restore VGA and video control
  912. //
  913. saveVGA = (saveVGA << 8) | PERMEDIA_VGA_CTRL_INDEX;
  914. VideoPortWriteRegisterUshort(PERMEDIA_MMVGA_INDEX_REG, saveVGA);
  915. VideoPortWriteRegisterUlong(VIDEO_CONTROL, saveVidCtl);
  916. }
  917. }
  918. VideoPortWriteRegisterUlong(APERTURE_ONE, 0x0);
  919. VideoPortWriteRegisterUlong(APERTURE_TWO, 0x0);
  920. VideoPortWriteRegisterUlong(BYPASS_WRITE_MASK, 0xFFFFFFFF);
  921. if (pciAccessRange == NULL)
  922. {
  923. return TRUE;
  924. }
  925. fbMappedSize = pciAccessRange[PCI_FB_BASE_INDEX].RangeLength;
  926. i = VideoPortReadRegisterUlong(MEM_CONFIG);
  927. //
  928. // MEM_CONFIG doesn't have the number of memory banks defined
  929. // at boot-time for P2: set up the board for 8MB. Can't do this
  930. // if the VGA is running, but that's OK. The VGA has set this
  931. // register to what we want.
  932. //
  933. if (!hwDeviceExtension->bVGAEnabled)
  934. {
  935. i |= (3 << 29);
  936. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength =
  937. (((i >> 29) & 0x3) + 1) * (2*1024*1024);
  938. VideoPortWriteRegisterUlong(MEM_CONFIG, i);
  939. VideoPortStallExecution(10);
  940. }
  941. testPattern = 0x55aa33cc;
  942. probeSize = (128 * 1024 / sizeof(ULONG)); // In DWords
  943. //
  944. // Dynamically size the SGRAM. Sample every 128K. If you happen to
  945. // have some VERY odd SGRAM size you may need cut this down. After
  946. // each write to the probe address, write to SGRAM address zero to
  947. // clear the PCI data bus. Otherwise, if we read from fresh air the
  948. // written value may be floating on the bus and the read give it back
  949. // to us.
  950. //
  951. // Note, if the memory wraps around at the end, then a different
  952. // algorithm must be used (which waits for address zero to become
  953. // equal to the address being written).
  954. //
  955. // Any valid pixel that we probe, we save and restore. This is to
  956. // avoid dots on the screen if we have booted onto the Permedia2 board.
  957. //
  958. pVStart = (PULONG)hwDeviceExtension->pFramebuffer;
  959. pVEnd = (PULONG)((ULONG_PTR)pVStart + fbMappedSize);
  960. //
  961. // check out address zero
  962. //
  963. save0 = VideoPortReadRegisterUlong(pVStart);
  964. save1 = VideoPortReadRegisterUlong(pVStart+1);
  965. VideoPortWriteRegisterUlong(pVStart, testPattern);
  966. VideoPortWriteRegisterUlong(pVStart+1, 0);
  967. if ((temp = VideoPortReadRegisterUlong(pVStart)) != testPattern)
  968. {
  969. DEBUG_PRINT((1, "cannot access SGRAM. Expected 0x%x, got 0x%x\n",
  970. testPattern, temp));
  971. return FALSE;
  972. }
  973. VideoPortWriteRegisterUlong(pVStart+1, save1);
  974. for (pV = pVStart + probeSize; pV < pVEnd; pV += probeSize)
  975. {
  976. save1 = VideoPortReadRegisterUlong(pV);
  977. VideoPortWriteRegisterUlong(pV, testPattern);
  978. VideoPortWriteRegisterUlong(pVStart, 0);
  979. if ((temp = VideoPortReadRegisterUlong(pV)) != testPattern)
  980. {
  981. DEBUG_PRINT((1, "PERM2: FB probe failed at offset 0x%x\n",
  982. (LONG)((LONG_PTR)pV - (LONG_PTR)pVStart)));
  983. DEBUG_PRINT((1, "PERM2: \tread back 0x%x, wanted 0x%x\n",
  984. temp, testPattern));
  985. break;
  986. }
  987. VideoPortWriteRegisterUlong(pV, save1);
  988. }
  989. VideoPortWriteRegisterUlong(pVStart, save0);
  990. if (pV < pVEnd)
  991. {
  992. //
  993. // I could also set MEM_CONFIG to the correct value here as we
  994. // now know the size of SGRAM, but as it's never used again
  995. // I won't bother
  996. //
  997. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength =
  998. (ULONG)((ULONG_PTR)pV - (ULONG_PTR)pVStart);
  999. DEBUG_PRINT((1, "PERM2: SGRAM dynamically resized to length 0x%x\n",
  1000. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength));
  1001. }
  1002. if (pciAccessRange[PCI_FB_BASE_INDEX].RangeLength > fbMappedSize)
  1003. {
  1004. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength = fbMappedSize;
  1005. }
  1006. DEBUG_PRINT((2, "PERM2: got a size of 0x%x bytes\n",
  1007. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength));
  1008. //
  1009. // finally, if the SGRAM size is actually smaller than the region that
  1010. // we probed, remap to the smaller size to save on page table entries.
  1011. // Not doing this causes some systems to run out of PTEs.
  1012. //
  1013. if (fbMappedSize > pciAccessRange[PCI_FB_BASE_INDEX].RangeLength)
  1014. {
  1015. VideoPortFreeDeviceBase(HwDeviceExtension,
  1016. hwDeviceExtension->pFramebuffer);
  1017. if ( (hwDeviceExtension->pFramebuffer =
  1018. VideoPortGetDeviceBase(HwDeviceExtension,
  1019. pciAccessRange[PCI_FB_BASE_INDEX].RangeStart,
  1020. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength,
  1021. (UCHAR) hwDeviceExtension->PhysicalFrameIoSpace)) == NULL)
  1022. {
  1023. //
  1024. // this shouldn't happen but we'd better check
  1025. //
  1026. DEBUG_PRINT((0, "Remap of framebuffer to smaller size failed!!!\n"));
  1027. return FALSE;
  1028. }
  1029. DEBUG_PRINT((1, "PERM2: Remapped framebuffer memory to 0x%x, size 0x%x\n",
  1030. hwDeviceExtension->pFramebuffer,
  1031. pciAccessRange[PCI_FB_BASE_INDEX].RangeLength));
  1032. }
  1033. //
  1034. // PERMEDIA2 has no localbuffer
  1035. //
  1036. hwDeviceExtension->deviceInfo.LocalbufferWidth = 0;
  1037. hwDeviceExtension->deviceInfo.LocalbufferLength = 0;
  1038. return TRUE;
  1039. }
  1040. BOOLEAN
  1041. Permedia2Initialize(
  1042. PVOID HwDeviceExtension
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. This routine does one time initialization of the device.
  1047. Arguments:
  1048. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  1049. Return Value:
  1050. Returns TRUE when success.
  1051. --*/
  1052. {
  1053. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1054. ULONG ulValue;
  1055. P2_DECL;
  1056. //
  1057. // always initialize the IRQ control block...
  1058. // the memory is used to store information which is global to all
  1059. // driver instances of a display card by the display driver
  1060. //
  1061. if ( hwDeviceExtension->NtVersion == WIN2K)
  1062. {
  1063. if (!Permedia2InitializeInterruptBlock(hwDeviceExtension))
  1064. {
  1065. DEBUG_PRINT((0, "PERM2: failed to initialize the IRQ control block\n"));
  1066. return FALSE;
  1067. }
  1068. }
  1069. //
  1070. // Clear the framebuffer.
  1071. //
  1072. VideoPortZeroDeviceMemory(hwDeviceExtension->pFramebuffer,
  1073. hwDeviceExtension->AdapterMemorySize);
  1074. return TRUE;
  1075. } // end Permedia2Initialize()
  1076. BOOLEAN
  1077. Permedia2StartIO(
  1078. PVOID HwDeviceExtension,
  1079. PVIDEO_REQUEST_PACKET RequestPacket
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. This routine is the main execution routine for the miniport driver. It
  1084. accepts a Video Request Packet, performs the request, and then returns
  1085. with the appropriate status.
  1086. Arguments:
  1087. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  1088. RequestPacket - Pointer to the video request packet. This structure
  1089. contains all the parameters passed to the VideoIoControl function.
  1090. Return Value:
  1091. --*/
  1092. {
  1093. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1094. P2_DECL;
  1095. VP_STATUS status;
  1096. PVIDEO_MODE_INFORMATION modeInformation;
  1097. PVIDEO_MEMORY_INFORMATION memoryInformation;
  1098. PVIDEOPARAMETERS pVideoParams;
  1099. PVIDEO_CLUT clutBuffer;
  1100. ULONG inIoSpace;
  1101. ULONG RequestedMode;
  1102. ULONG modeNumber;
  1103. ULONG ulValue;
  1104. HANDLE ProcessHandle;
  1105. PP2_VIDEO_MODES ModeEntry;
  1106. P2_VIDEO_FREQUENCIES FrequencyEntry, *pFrequencyEntry;
  1107. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  1108. //
  1109. // Switch on the IoContolCode in the RequestPacket. It indicates which
  1110. // function must be performed by the driver.
  1111. //
  1112. switch (RequestPacket->IoControlCode)
  1113. {
  1114. case IOCTL_VIDEO_QUERY_REGISTRY_DWORD:
  1115. {
  1116. DEBUG_PRINT((2, "PERM2: got IOCTL_VIDEO_QUERY_REGISTRY_DWORD\n"));
  1117. if (RequestPacket->OutputBufferLength <
  1118. (RequestPacket->StatusBlock->Information = sizeof(ULONG)))
  1119. {
  1120. status = ERROR_INSUFFICIENT_BUFFER;
  1121. break;
  1122. }
  1123. if (VideoPortGetRegistryParameters( HwDeviceExtension,
  1124. RequestPacket->InputBuffer,
  1125. FALSE,
  1126. Permedia2RegistryCallback,
  1127. &ulValue) != NO_ERROR )
  1128. {
  1129. DEBUG_PRINT((1, "PERM2: IOCTL_VIDEO_QUERY_REGISTRY_DWORD failed\n"));
  1130. status = ERROR_INVALID_PARAMETER;
  1131. break;
  1132. }
  1133. *(PULONG)(RequestPacket->OutputBuffer) = ulValue;
  1134. status = NO_ERROR;
  1135. break;
  1136. }
  1137. case IOCTL_VIDEO_REG_SAVE_GAMMA_LUT:
  1138. {
  1139. DEBUG_PRINT((2, "PERM2: got IOCTL_VIDEO_REG_SAVE_GAMMA_LUT\n"));
  1140. if (RequestPacket->InputBufferLength <
  1141. (RequestPacket->StatusBlock->Information = MAX_CLUT_SIZE))
  1142. {
  1143. status = ERROR_INSUFFICIENT_BUFFER;
  1144. break;
  1145. }
  1146. status = VideoPortSetRegistryParameters( HwDeviceExtension,
  1147. L"DisplayGammaLUT",
  1148. RequestPacket->InputBuffer,
  1149. MAX_CLUT_SIZE);
  1150. break;
  1151. }
  1152. case IOCTL_VIDEO_REG_RETRIEVE_GAMMA_LUT:
  1153. {
  1154. DEBUG_PRINT((2, "PERM2: got IOCTL_VIDEO_REG_RETRIEVE_GAMMA_LUT\n"));
  1155. if (RequestPacket->OutputBufferLength <
  1156. (RequestPacket->StatusBlock->Information = MAX_CLUT_SIZE))
  1157. {
  1158. status = ERROR_INSUFFICIENT_BUFFER;
  1159. break;
  1160. }
  1161. status = VideoPortGetRegistryParameters( HwDeviceExtension,
  1162. L"DisplayGammaLUT",
  1163. FALSE,
  1164. Permedia2RetrieveGammaCallback,
  1165. RequestPacket->InputBuffer);
  1166. break;
  1167. }
  1168. case IOCTL_VIDEO_QUERY_DEVICE_INFO:
  1169. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QUERY_deviceInfo\n"));
  1170. if ( RequestPacket->OutputBufferLength <
  1171. (RequestPacket->StatusBlock->Information = sizeof(P2_Device_Info)))
  1172. {
  1173. status = ERROR_INSUFFICIENT_BUFFER;
  1174. break;
  1175. }
  1176. //
  1177. // Copy our local PCI info to the output buffer
  1178. //
  1179. *(P2_Device_Info *)(RequestPacket->OutputBuffer) =
  1180. hwDeviceExtension->deviceInfo;
  1181. status = NO_ERROR;
  1182. break;
  1183. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  1184. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - MapVideoMemory\n"));
  1185. if ( ( RequestPacket->OutputBufferLength <
  1186. ( RequestPacket->StatusBlock->Information =
  1187. sizeof(VIDEO_MEMORY_INFORMATION) ) ) ||
  1188. ( RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY) ) )
  1189. {
  1190. status = ERROR_INSUFFICIENT_BUFFER;
  1191. break;
  1192. }
  1193. memoryInformation = RequestPacket->OutputBuffer;
  1194. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  1195. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  1196. memoryInformation->VideoRamLength =
  1197. hwDeviceExtension->FrameLength;
  1198. inIoSpace = hwDeviceExtension->PhysicalFrameIoSpace;
  1199. //
  1200. // Performance:
  1201. //
  1202. // Enable USWC
  1203. // We only do it for the frame buffer - memory mapped registers can
  1204. // not be mapped USWC because write combining the registers would
  1205. // cause very bad things to happen !
  1206. //
  1207. status = VideoPortMapMemory( HwDeviceExtension,
  1208. hwDeviceExtension->PhysicalFrameAddress,
  1209. &(memoryInformation->VideoRamLength),
  1210. &inIoSpace,
  1211. &(memoryInformation->VideoRamBase));
  1212. if (status != NO_ERROR)
  1213. {
  1214. DEBUG_PRINT((1, "PERM2: VideoPortMapMemory failed with error %d\n", status));
  1215. break;
  1216. }
  1217. //
  1218. // The frame buffer and virtual memory and equivalent in this
  1219. // case.
  1220. //
  1221. memoryInformation->FrameBufferBase =
  1222. memoryInformation->VideoRamBase;
  1223. memoryInformation->FrameBufferLength =
  1224. memoryInformation->VideoRamLength;
  1225. break;
  1226. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  1227. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - UnMapVideoMemory\n"));
  1228. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  1229. {
  1230. status = ERROR_INSUFFICIENT_BUFFER;
  1231. break;
  1232. }
  1233. status = VideoPortUnmapMemory(
  1234. HwDeviceExtension,
  1235. ((PVIDEO_MEMORY)(RequestPacket->InputBuffer))->
  1236. RequestedVirtualAddress,
  1237. 0 );
  1238. break;
  1239. case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
  1240. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QueryPublicAccessRanges\n"));
  1241. {
  1242. PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
  1243. ULONG physicalPortLength;
  1244. PVOID VirtualAddress;
  1245. PHYSICAL_ADDRESS PhysicalAddress;
  1246. if ( ( RequestPacket->OutputBufferLength <
  1247. ( RequestPacket->StatusBlock->Information =
  1248. sizeof(VIDEO_PUBLIC_ACCESS_RANGES))) ||
  1249. ( RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY) ) )
  1250. {
  1251. status = ERROR_INSUFFICIENT_BUFFER;
  1252. break;
  1253. }
  1254. ProcessHandle = (HANDLE)(((PVIDEO_MEMORY)
  1255. (RequestPacket->InputBuffer))->RequestedVirtualAddress);
  1256. if (ProcessHandle != (HANDLE)0)
  1257. {
  1258. //
  1259. // map 4K area for a process
  1260. //
  1261. DEBUG_PRINT((2, "PERM2: Mapping in 4K area from Control registers\n"));
  1262. VirtualAddress = (PVOID)ProcessHandle;
  1263. PhysicalAddress = hwDeviceExtension->PhysicalRegisterAddress;
  1264. PhysicalAddress.LowPart += 0x2000;
  1265. physicalPortLength = 0x1000;
  1266. }
  1267. else
  1268. {
  1269. DEBUG_PRINT((2, "PERM2: Mapping in all Control registers\n"));
  1270. VirtualAddress = NULL;
  1271. PhysicalAddress = hwDeviceExtension->PhysicalRegisterAddress;
  1272. physicalPortLength = hwDeviceExtension->RegisterLength;
  1273. }
  1274. portAccess = RequestPacket->OutputBuffer;
  1275. portAccess->VirtualAddress = VirtualAddress;
  1276. portAccess->InIoSpace = hwDeviceExtension->RegisterSpace;
  1277. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1278. status = VideoPortMapMemory( HwDeviceExtension,
  1279. PhysicalAddress,
  1280. &physicalPortLength,
  1281. &(portAccess->MappedInIoSpace),
  1282. &(portAccess->VirtualAddress));
  1283. if (status == NO_ERROR)
  1284. {
  1285. DEBUG_PRINT((1, "PERM2: mapped PAR[0] at vaddr 0x%x for length 0x%x\n",
  1286. portAccess->VirtualAddress,
  1287. physicalPortLength));
  1288. }
  1289. else
  1290. {
  1291. DEBUG_PRINT((1, "PERM2: VideoPortMapMemory failed with status 0x%x\n", status));
  1292. }
  1293. if ( (RequestPacket->OutputBufferLength >=
  1294. 3 * sizeof(VIDEO_PUBLIC_ACCESS_RANGES) ) &&
  1295. (ProcessHandle == (HANDLE)0) )
  1296. {
  1297. RequestPacket->StatusBlock->Information =
  1298. 3 * sizeof(VIDEO_PUBLIC_ACCESS_RANGES);
  1299. portAccess = RequestPacket->OutputBuffer;
  1300. PhysicalAddress = hwDeviceExtension->PhysicalRegisterAddress;
  1301. physicalPortLength = hwDeviceExtension->RegisterLength;
  1302. #if defined(_ALPHA_)
  1303. //
  1304. // for alpha, we want to map in a dense version of the
  1305. // control registers if we can. If this fails, we null
  1306. // the virtual address
  1307. //
  1308. portAccess += 2;
  1309. portAccess->VirtualAddress = NULL;
  1310. portAccess->InIoSpace = hwDeviceExtension->RegisterSpace;
  1311. portAccess->MappedInIoSpace = 4;
  1312. status = VideoPortMapMemory( HwDeviceExtension,
  1313. PhysicalAddress,
  1314. &physicalPortLength,
  1315. &(portAccess->MappedInIoSpace),
  1316. &(portAccess->VirtualAddress));
  1317. if (status == NO_ERROR)
  1318. {
  1319. DEBUG_PRINT((1, "PERM2: mapped dense PAR[0] at vaddr 0x%x for length 0x%x\n",
  1320. portAccess->VirtualAddress,
  1321. physicalPortLength));
  1322. }
  1323. else
  1324. {
  1325. DEBUG_PRINT((1, "PERM2: dense VideoPortMapMemory failed with status 0x%x\n", status));
  1326. }
  1327. #else
  1328. //
  1329. // all others, we just copy range[0]
  1330. //
  1331. portAccess[2] = portAccess[0];
  1332. #endif
  1333. }
  1334. }
  1335. break;
  1336. case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
  1337. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - FreePublicAccessRanges\n"));
  1338. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  1339. {
  1340. status = ERROR_INSUFFICIENT_BUFFER;
  1341. break;
  1342. }
  1343. status = VideoPortUnmapMemory(
  1344. HwDeviceExtension,
  1345. ((PVIDEO_MEMORY)(RequestPacket->InputBuffer))->
  1346. RequestedVirtualAddress,
  1347. 0);
  1348. if (status != NO_ERROR)
  1349. {
  1350. DEBUG_PRINT((1, "PERM2: VideoPortUnmapMemory failed with status 0x%x\n", status));
  1351. }
  1352. #if defined(_ALPHA_)
  1353. {
  1354. PVIDEO_MEMORY pVideoMemory;
  1355. PVOID pVirtualAddress;
  1356. if (RequestPacket->InputBufferLength >= 3 * sizeof(VIDEO_MEMORY))
  1357. {
  1358. pVideoMemory = (PVIDEO_MEMORY)(RequestPacket->InputBuffer);
  1359. pVirtualAddress = pVideoMemory->RequestedVirtualAddress;
  1360. pVideoMemory += 2;
  1361. if((pVideoMemory->RequestedVirtualAddress) &&
  1362. (pVideoMemory->RequestedVirtualAddress != pVirtualAddress))
  1363. {
  1364. status = VideoPortUnmapMemory(
  1365. HwDeviceExtension,
  1366. pVideoMemory->RequestedVirtualAddress,
  1367. 0 );
  1368. }
  1369. if (status != NO_ERROR)
  1370. DEBUG_PRINT((1, "PERM2: VideoPortUnmapMemory failed on Alpha with status 0x%x\n", status));
  1371. }
  1372. }
  1373. #endif
  1374. break;
  1375. case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
  1376. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - HandleVideoParameters\n"));
  1377. //
  1378. // We don't support a tv connector so just return NO_ERROR here
  1379. //
  1380. pVideoParams = (PVIDEOPARAMETERS) (RequestPacket->InputBuffer);
  1381. if (pVideoParams->dwCommand == VP_COMMAND_GET)
  1382. {
  1383. pVideoParams = (PVIDEOPARAMETERS) (RequestPacket->OutputBuffer);
  1384. pVideoParams->dwFlags = 0;
  1385. }
  1386. RequestPacket->StatusBlock->Information = sizeof(VIDEOPARAMETERS);
  1387. status = NO_ERROR;
  1388. break;
  1389. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  1390. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QueryAvailableModes\n"));
  1391. if (RequestPacket->OutputBufferLength <
  1392. ( RequestPacket->StatusBlock->Information =
  1393. hwDeviceExtension->NumAvailableModes *
  1394. sizeof(VIDEO_MODE_INFORMATION)) )
  1395. {
  1396. status = ERROR_INSUFFICIENT_BUFFER;
  1397. } else
  1398. {
  1399. modeInformation = RequestPacket->OutputBuffer;
  1400. for (pFrequencyEntry = hwDeviceExtension->FrequencyTable;
  1401. pFrequencyEntry->BitsPerPel != 0;
  1402. pFrequencyEntry++)
  1403. {
  1404. if (pFrequencyEntry->ModeValid)
  1405. {
  1406. *modeInformation =
  1407. pFrequencyEntry->ModeEntry->ModeInformation;
  1408. modeInformation->Frequency =
  1409. pFrequencyEntry->ScreenFrequency;
  1410. modeInformation->ModeIndex =
  1411. pFrequencyEntry->ModeIndex;
  1412. modeInformation++;
  1413. }
  1414. }
  1415. status = NO_ERROR;
  1416. }
  1417. break;
  1418. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  1419. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QueryCurrentModes. current mode is %d\n",
  1420. hwDeviceExtension->ActiveModeEntry->ModeInformation.ModeIndex));
  1421. if (RequestPacket->OutputBufferLength <
  1422. (RequestPacket->StatusBlock->Information =
  1423. sizeof(VIDEO_MODE_INFORMATION)) )
  1424. {
  1425. status = ERROR_INSUFFICIENT_BUFFER;
  1426. } else
  1427. {
  1428. *((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) =
  1429. hwDeviceExtension->ActiveModeEntry->ModeInformation;
  1430. ((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer)->Frequency =
  1431. hwDeviceExtension->ActiveFrequencyEntry.ScreenFrequency;
  1432. status = NO_ERROR;
  1433. }
  1434. break;
  1435. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  1436. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QueryNumAvailableModes (= %d)\n",
  1437. hwDeviceExtension->NumAvailableModes));
  1438. //
  1439. // Find out the size of the data to be put in the the buffer and
  1440. // return that in the status information (whether or not the
  1441. // information is there). If the buffer passed in is not large
  1442. // enough return an appropriate error code.
  1443. //
  1444. if (RequestPacket->OutputBufferLength <
  1445. (RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES)))
  1446. {
  1447. status = ERROR_INSUFFICIENT_BUFFER;
  1448. } else
  1449. {
  1450. //
  1451. // Configure the valid modes again. This allows non 3D accelerated
  1452. // modes to be added dynamically. BUT, we cannot allow modes to be
  1453. // dynamically removed. If we do we may have nowhere to go after
  1454. // the Test screen (or if we logout). So only reconfigure these
  1455. // modes if the ExportNon3D flag is turned on and it used to be
  1456. // off. If it was already on then there's no need to reconfigure.
  1457. //
  1458. if (!hwDeviceExtension->ExportNon3DModes)
  1459. {
  1460. ULONG ExportNon3DModes = 0;
  1461. status = VideoPortGetRegistryParameters(HwDeviceExtension,
  1462. PERM2_EXPORT_HIRES_REG_STRING,
  1463. FALSE,
  1464. Permedia2RegistryCallback,
  1465. &ExportNon3DModes);
  1466. if (( status == NO_ERROR) && ExportNon3DModes)
  1467. {
  1468. ConstructValidModesList( HwDeviceExtension,
  1469. hwDeviceExtension );
  1470. }
  1471. }
  1472. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
  1473. hwDeviceExtension->NumAvailableModes;
  1474. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
  1475. sizeof(VIDEO_MODE_INFORMATION);
  1476. status = NO_ERROR;
  1477. }
  1478. break;
  1479. case IOCTL_VIDEO_SET_CURRENT_MODE:
  1480. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - SetCurrentMode\n"));
  1481. if(!hwDeviceExtension->bVGAEnabled)
  1482. {
  1483. //
  1484. // secondary card: if it's just returned from hibernation
  1485. // it won't be set-up yet
  1486. // NB. primary is OK, its BIOS has run
  1487. //
  1488. PCI_COMMON_CONFIG PciData;
  1489. VideoPortGetBusData(hwDeviceExtension,
  1490. PCIConfiguration,
  1491. 0,
  1492. &PciData,
  1493. 0,
  1494. PCI_COMMON_HDR_LENGTH);
  1495. if((PciData.Command & PCI_ENABLE_MEMORY_SPACE) == 0)
  1496. {
  1497. //
  1498. // memory accesses not turned on - this card has just returned
  1499. // from hibernation and is back in its default state: set it
  1500. // up once more
  1501. //
  1502. PowerOnReset(hwDeviceExtension);
  1503. }
  1504. }
  1505. //
  1506. // Check if the size of the data in the input buffer is large enough.
  1507. //
  1508. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
  1509. {
  1510. RequestPacket->StatusBlock->Information = sizeof(VIDEO_MODE);
  1511. status = ERROR_INSUFFICIENT_BUFFER;
  1512. break;
  1513. }
  1514. //
  1515. // Find the correct entries in the P2_VIDEO_MODES and
  1516. // P2_VIDEO_FREQUENCIES tables that correspond to this
  1517. // mode number.
  1518. //
  1519. // ( Remember that each mode in the P2_VIDEO_MODES table
  1520. // can have a number of possible frequencies associated with it.)
  1521. //
  1522. RequestedMode = ((PVIDEO_MODE) RequestPacket->InputBuffer)->RequestedMode;
  1523. modeNumber = RequestedMode & ~VIDEO_MODE_NO_ZERO_MEMORY;
  1524. if ((modeNumber >= hwDeviceExtension->NumTotalModes) ||
  1525. !(hwDeviceExtension->FrequencyTable[modeNumber].ModeValid))
  1526. {
  1527. RequestPacket->StatusBlock->Information =
  1528. hwDeviceExtension->NumTotalModes;
  1529. status = ERROR_INVALID_PARAMETER;
  1530. break;
  1531. }
  1532. //
  1533. // Re-sample the clock speed. This allows us to change the clock speed
  1534. // on the fly using the display applet Test button.
  1535. //
  1536. Permedia2GetClockSpeeds(HwDeviceExtension);
  1537. FrequencyEntry = hwDeviceExtension->FrequencyTable[modeNumber];
  1538. ModeEntry = FrequencyEntry.ModeEntry;
  1539. //
  1540. // At this point, 'ModeEntry' and 'FrequencyEntry' point to the
  1541. // necessary table entries required for setting the requested mode.
  1542. //
  1543. // Zero the DAC and the Screen buffer memory.
  1544. //
  1545. ZeroMemAndDac(hwDeviceExtension, RequestedMode);
  1546. ModeEntry->ModeInformation.DriverSpecificAttributeFlags =
  1547. hwDeviceExtension->Capabilities;
  1548. //
  1549. // For low resolution modes we may have to do various tricks
  1550. // such as line doubling and getting the RAMDAC to zoom.
  1551. // Record any such zoom in the Mode DeviceAttributes field.
  1552. // Primarily this is to allow the display driver to
  1553. // compensate when asked to move the cursor or change its
  1554. // shape.
  1555. //
  1556. // Currently, low res means lower than 512 pixels width.
  1557. //
  1558. if (FrequencyEntry.ScreenWidth < 512)
  1559. {
  1560. // Permedia does line doubling. If using a TVP we must
  1561. // get it to zoom by 2 in X to get the pixel rate up.
  1562. //
  1563. ModeEntry->ModeInformation.DriverSpecificAttributeFlags |= CAPS_ZOOM_Y_BY2;
  1564. }
  1565. if (!InitializeVideo(HwDeviceExtension, &FrequencyEntry))
  1566. {
  1567. DEBUG_PRINT((1, "PERM2: InitializeVideo failed\n"));
  1568. RequestPacket->StatusBlock->Information = modeNumber;
  1569. status = ERROR_INVALID_PARAMETER;
  1570. break;
  1571. }
  1572. //
  1573. // Save the mode since we know the rest will work.
  1574. //
  1575. hwDeviceExtension->ActiveModeEntry = ModeEntry;
  1576. hwDeviceExtension->ActiveFrequencyEntry = FrequencyEntry;
  1577. //
  1578. // Update VIDEO_MODE_INFORMATION fields
  1579. //
  1580. // Now that we've set the mode, we now know the screen stride, and
  1581. // so can update some fields in the VIDEO_MODE_INFORMATION
  1582. // structure for this mode. The Permedia 2 display driver is expected
  1583. // to call IOCTL_VIDEO_QUERY_CURRENT_MODE to query these corrected
  1584. // values.
  1585. //
  1586. //
  1587. // Calculate the bitmap width (note the '+ 1' on BitsPerPlane is
  1588. // so that '15bpp' works out right). 12bpp is special in that we
  1589. // support it as sparse nibbles within a 32-bit pixel. ScreenStride
  1590. // is in bytes; VideoMemoryBitmapWidth is measured in pixels;
  1591. //
  1592. if (ModeEntry->ModeInformation.BitsPerPlane != 12)
  1593. {
  1594. ModeEntry->ModeInformation.VideoMemoryBitmapWidth =
  1595. ModeEntry->ModeInformation.ScreenStride
  1596. / ((ModeEntry->ModeInformation.BitsPerPlane + 1) >> 3);
  1597. }
  1598. else
  1599. {
  1600. ModeEntry->ModeInformation.VideoMemoryBitmapWidth =
  1601. ModeEntry->ModeInformation.ScreenStride >> 2;
  1602. }
  1603. //
  1604. // Calculate the bitmap height.
  1605. //
  1606. ulValue = hwDeviceExtension->AdapterMemorySize;
  1607. ModeEntry->ModeInformation.VideoMemoryBitmapHeight =
  1608. ulValue / ModeEntry->ModeInformation.ScreenStride;
  1609. status = NO_ERROR;
  1610. break;
  1611. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  1612. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - SetColorRegs\n"));
  1613. clutBuffer = (PVIDEO_CLUT) RequestPacket->InputBuffer;
  1614. status = Permedia2SetColorLookup(hwDeviceExtension,
  1615. clutBuffer,
  1616. RequestPacket->InputBufferLength,
  1617. FALSE, // update when we need to
  1618. TRUE); // Update cache entries as
  1619. // well as RAMDAC
  1620. break;
  1621. case IOCTL_VIDEO_RESET_DEVICE:
  1622. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - RESET_DEVICE\n"));
  1623. if(hwDeviceExtension->bVGAEnabled)
  1624. {
  1625. //
  1626. // Do any resets required before getting the BIOS to
  1627. // do an INT 10
  1628. //
  1629. //
  1630. // reset the VGA before rerouting the bypass to display VGA
  1631. //
  1632. // Only reset the device if the monitor is on. If it is off,
  1633. // then executing the int10 will turn it back on.
  1634. //
  1635. if (hwDeviceExtension->bMonitorPoweredOn)
  1636. {
  1637. //
  1638. // Do an Int10 to mode 3 will put the VGA to a known state.
  1639. //
  1640. VideoPortZeroMemory(&biosArguments,
  1641. sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1642. biosArguments.Eax = 0x0003;
  1643. VideoPortInt10(HwDeviceExtension, &biosArguments);
  1644. }
  1645. }
  1646. status = NO_ERROR;
  1647. break;
  1648. case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
  1649. {
  1650. PVIDEO_SHARE_MEMORY pShareMemory;
  1651. PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
  1652. PHYSICAL_ADDRESS shareAddress;
  1653. PVOID virtualAddress;
  1654. ULONG sharedViewSize;
  1655. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - ShareVideoMemory\n"));
  1656. if( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
  1657. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
  1658. {
  1659. DEBUG_PRINT((1, "PERM2: IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INSUFFICIENT_BUFFER\n"));
  1660. status = ERROR_INSUFFICIENT_BUFFER;
  1661. break;
  1662. }
  1663. pShareMemory = RequestPacket->InputBuffer;
  1664. if( (pShareMemory->ViewOffset > hwDeviceExtension->AdapterMemorySize) ||
  1665. ((pShareMemory->ViewOffset + pShareMemory->ViewSize) >
  1666. hwDeviceExtension->AdapterMemorySize) )
  1667. {
  1668. DEBUG_PRINT((1, "PERM2: IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INVALID_PARAMETER\n"));
  1669. status = ERROR_INVALID_PARAMETER;
  1670. break;
  1671. }
  1672. RequestPacket->StatusBlock->Information =
  1673. sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  1674. //
  1675. // Beware: the input buffer and the output buffer are the same
  1676. // buffer, and therefore data should not be copied from one to the
  1677. // other
  1678. //
  1679. virtualAddress = pShareMemory->ProcessHandle;
  1680. sharedViewSize = pShareMemory->ViewSize;
  1681. inIoSpace = hwDeviceExtension->PhysicalFrameIoSpace;
  1682. //
  1683. // NOTE: we are ignoring ViewOffset
  1684. //
  1685. shareAddress.QuadPart =
  1686. hwDeviceExtension->PhysicalFrameAddress.QuadPart;
  1687. //
  1688. // Unlike the MAP_MEMORY IOCTL, in this case we can not map extra
  1689. // address space since the application could actually use the
  1690. // pointer we return to it to touch locations in the address space
  1691. // that do not have actual video memory in them.
  1692. //
  1693. // An app doing this would cause the machine to crash.
  1694. //
  1695. status = VideoPortMapMemory( hwDeviceExtension,
  1696. shareAddress,
  1697. &sharedViewSize,
  1698. &inIoSpace,
  1699. &virtualAddress );
  1700. pShareMemoryInformation = RequestPacket->OutputBuffer;
  1701. pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
  1702. pShareMemoryInformation->VirtualAddress = virtualAddress;
  1703. pShareMemoryInformation->SharedViewSize = sharedViewSize;
  1704. }
  1705. break;
  1706. case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
  1707. {
  1708. PVIDEO_SHARE_MEMORY pShareMemory;
  1709. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - UnshareVideoMemory\n"));
  1710. if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
  1711. {
  1712. status = ERROR_INSUFFICIENT_BUFFER;
  1713. break;
  1714. }
  1715. pShareMemory = RequestPacket->InputBuffer;
  1716. status = VideoPortUnmapMemory(hwDeviceExtension,
  1717. pShareMemory->RequestedVirtualAddress,
  1718. pShareMemory->ProcessHandle);
  1719. }
  1720. break;
  1721. case IOCTL_VIDEO_QUERY_LINE_DMA_BUFFER:
  1722. //
  1723. // Return the line DMA buffer information. The buffer size and
  1724. // virtual address will be zero if the buffer couldn't be allocated.
  1725. //
  1726. // output buffer has zero length, so free buffer....
  1727. //
  1728. status = ERROR_INSUFFICIENT_BUFFER;
  1729. if (RequestPacket->OutputBufferLength <
  1730. (RequestPacket->StatusBlock->Information = sizeof(LINE_DMA_BUFFER)))
  1731. {
  1732. //
  1733. // Maybe we should free something
  1734. //
  1735. if ( RequestPacket->InputBufferLength >= sizeof(LINE_DMA_BUFFER))
  1736. {
  1737. if (hwDeviceExtension->ulLineDMABufferUsage > 0)
  1738. {
  1739. hwDeviceExtension->ulLineDMABufferUsage--;
  1740. if (hwDeviceExtension->ulLineDMABufferUsage == 0)
  1741. {
  1742. VideoPortFreeCommonBuffer(
  1743. hwDeviceExtension,
  1744. hwDeviceExtension->LineDMABuffer.size,
  1745. hwDeviceExtension->LineDMABuffer.virtAddr,
  1746. hwDeviceExtension->LineDMABuffer.physAddr,
  1747. hwDeviceExtension->LineDMABuffer.cacheEnabled);
  1748. memset(&hwDeviceExtension->LineDMABuffer,
  1749. 0,
  1750. sizeof(LINE_DMA_BUFFER));
  1751. }
  1752. }
  1753. status = NO_ERROR;
  1754. }
  1755. }
  1756. else
  1757. {
  1758. PLINE_DMA_BUFFER pDMAIn, pDMAOut;
  1759. pDMAIn = (PLINE_DMA_BUFFER)RequestPacket->InputBuffer;
  1760. pDMAOut = (PLINE_DMA_BUFFER)RequestPacket->OutputBuffer;
  1761. if (RequestPacket->InputBufferLength >= sizeof(LINE_DMA_BUFFER))
  1762. {
  1763. if (hwDeviceExtension->ulLineDMABufferUsage == 0)
  1764. {
  1765. *pDMAOut = *pDMAIn;
  1766. if( ( pDMAOut->virtAddr =
  1767. VideoPortGetCommonBuffer( hwDeviceExtension,
  1768. pDMAIn->size,
  1769. PAGE_SIZE,
  1770. &pDMAOut->physAddr,
  1771. &pDMAOut->size,
  1772. pDMAIn->cacheEnabled ) )
  1773. != NULL )
  1774. {
  1775. hwDeviceExtension->LineDMABuffer=*pDMAOut;
  1776. hwDeviceExtension->ulLineDMABufferUsage++;
  1777. }
  1778. } else
  1779. {
  1780. *pDMAOut = hwDeviceExtension->LineDMABuffer;
  1781. hwDeviceExtension->ulLineDMABufferUsage++;
  1782. }
  1783. status = NO_ERROR;
  1784. }
  1785. }
  1786. DEBUG_PRINT((1, "PERM2: QUERY LINE DMA BUFFER status %d\n", status));
  1787. break;
  1788. case IOCTL_VIDEO_QUERY_EMULATED_DMA_BUFFER:
  1789. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - QUERY EMULATED DMA BUFFER\n"));
  1790. //
  1791. // Allocate/free the emulated DMA buffer. The buffer size and
  1792. // virtual address will be zero if the buffer couldn't be allocated.
  1793. //
  1794. // output buffer has zero length, so free buffer....
  1795. //
  1796. status = ERROR_INSUFFICIENT_BUFFER;
  1797. if (RequestPacket->InputBufferLength >= sizeof(EMULATED_DMA_BUFFER))
  1798. {
  1799. PEMULATED_DMA_BUFFER pDMAIn, pDMAOut;
  1800. pDMAIn = (PEMULATED_DMA_BUFFER)RequestPacket->InputBuffer;
  1801. if (RequestPacket->OutputBufferLength <
  1802. (RequestPacket->StatusBlock->Information = sizeof(EMULATED_DMA_BUFFER)))
  1803. {
  1804. VideoPortFreePool(hwDeviceExtension, pDMAIn->virtAddr);
  1805. status = NO_ERROR;
  1806. }
  1807. else
  1808. {
  1809. pDMAOut = (PEMULATED_DMA_BUFFER)RequestPacket->OutputBuffer;
  1810. if ( ( pDMAOut->virtAddr =
  1811. VideoPortAllocatePool( hwDeviceExtension,
  1812. VpPagedPool,
  1813. pDMAIn->size,
  1814. pDMAIn->tag ) )
  1815. != NULL )
  1816. {
  1817. pDMAOut->size = pDMAIn->size;
  1818. pDMAOut->tag = pDMAIn->tag;
  1819. }
  1820. status = NO_ERROR;
  1821. }
  1822. }
  1823. DEBUG_PRINT((1, "PERM2: QUERY EMULATED DMA BUFFER status %d\n", status));
  1824. break;
  1825. case IOCTL_VIDEO_MAP_INTERRUPT_CMD_BUF:
  1826. DEBUG_PRINT((1, "PERM2: Permedia2StartIO - MapInterruptCmdBuf\n"));
  1827. if (RequestPacket->OutputBufferLength <
  1828. (RequestPacket->StatusBlock->Information =
  1829. sizeof(PVOID)) )
  1830. {
  1831. //
  1832. // They've give us a duff buffer.
  1833. //
  1834. status = ERROR_INSUFFICIENT_BUFFER;
  1835. }
  1836. else
  1837. {
  1838. *((PVOID*)(RequestPacket->OutputBuffer)) =
  1839. hwDeviceExtension->InterruptControl.ControlBlock;
  1840. status = NO_ERROR;
  1841. }
  1842. DEBUG_PRINT((1, "PERM2: MapInterruptCmdBuf returns va %x\n",
  1843. *(PULONG)(RequestPacket->OutputBuffer)));
  1844. break;
  1845. #if defined(_X86_)
  1846. case IOCTL_VIDEO_QUERY_INTERLOCKEDEXCHANGE:
  1847. status = ERROR_INSUFFICIENT_BUFFER;
  1848. if ( RequestPacket->OutputBufferLength >=
  1849. (RequestPacket->StatusBlock->Information = sizeof(PVOID)) )
  1850. {
  1851. PVOID *pIE = (PVOID)RequestPacket->OutputBuffer;
  1852. *pIE = (PVOID) VideoPortInterlockedExchange;
  1853. status = NO_ERROR;
  1854. }
  1855. break;
  1856. #endif
  1857. case IOCTL_VIDEO_STALL_EXECUTION:
  1858. if (RequestPacket->InputBufferLength >= sizeof(ULONG))
  1859. {
  1860. ULONG *pMicroseconds = (ULONG *)RequestPacket->InputBuffer;
  1861. VideoPortStallExecution(*pMicroseconds);
  1862. status = NO_ERROR;
  1863. } else
  1864. {
  1865. status = ERROR_INSUFFICIENT_BUFFER;
  1866. }
  1867. break;
  1868. //
  1869. // if we get here, an invalid IoControlCode was specified.
  1870. //
  1871. default:
  1872. DEBUG_PRINT((1, "Fell through Permedia2 startIO routine - invalid command\n"));
  1873. status = ERROR_INVALID_FUNCTION;
  1874. break;
  1875. }
  1876. RequestPacket->StatusBlock->Status = status;
  1877. if( status != NO_ERROR )
  1878. RequestPacket->StatusBlock->Information = 0;
  1879. return TRUE;
  1880. } // end Permedia2StartIO()
  1881. BOOLEAN
  1882. Permedia2ResetHW(
  1883. PVOID HwDeviceExtension,
  1884. ULONG Columns,
  1885. ULONG Rows
  1886. )
  1887. /*++
  1888. Routine Description:
  1889. This routine resets the hardware when a soft reboot is performed. We
  1890. need this to reset the VGA pass through.
  1891. THIS FUNCTION CANNOT BE PAGED.
  1892. Arguments:
  1893. hwDeviceExtension - Pointer to the miniport driver's device extension.
  1894. Columns - Specifies the number of columns of the mode to be set up.
  1895. Rows - Specifies the number of rows of the mode to be set up.
  1896. Return Value:
  1897. We always return FALSE to force the HAL to do an INT10 reset.
  1898. --*/
  1899. {
  1900. //
  1901. // return false so the HAL does an INT10 mode 3
  1902. //
  1903. return(FALSE);
  1904. }
  1905. VP_STATUS
  1906. Permedia2SetColorLookup(
  1907. PHW_DEVICE_EXTENSION hwDeviceExtension,
  1908. PVIDEO_CLUT ClutBuffer,
  1909. ULONG ClutBufferSize,
  1910. BOOLEAN ForceRAMDACWrite,
  1911. BOOLEAN UpdateCache
  1912. )
  1913. /*++
  1914. Routine Description:
  1915. This routine sets a specified portion of the color lookup table settings.
  1916. Arguments:
  1917. hwDeviceExtension - Pointer to the miniport driver's device extension.
  1918. ClutBufferSize - Length of the input buffer supplied by the user.
  1919. ClutBuffer - Pointer to the structure containing the color lookup table.
  1920. Return Value:
  1921. None.
  1922. --*/
  1923. {
  1924. USHORT i, j;
  1925. TVP4020_DECL;
  1926. P2RD_DECL;
  1927. PVIDEO_CLUT LUTCachePtr = &(hwDeviceExtension->LUTCache.LUTCache);
  1928. P2_DECL;
  1929. ULONG VsEnd;
  1930. //
  1931. // Check if the size of the data in the input buffer is large enough.
  1932. //
  1933. if ( (ClutBufferSize < (sizeof(VIDEO_CLUT) - sizeof(ULONG))) ||
  1934. (ClutBufferSize < (sizeof(VIDEO_CLUT) +
  1935. (sizeof(ULONG) * (ClutBuffer->NumEntries - 1))) ) )
  1936. {
  1937. DEBUG_PRINT((1, "PERM2: Permedia2SetColorLookup: insufficient buffer (was %d, min %d)\n",
  1938. ClutBufferSize,
  1939. (sizeof(VIDEO_CLUT) + (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)))));
  1940. return ERROR_INSUFFICIENT_BUFFER;
  1941. }
  1942. //
  1943. // Check to see if the parameters are valid.
  1944. //
  1945. if ( (ClutBuffer->NumEntries == 0) ||
  1946. (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
  1947. (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
  1948. VIDEO_MAX_COLOR_REGISTER + 1) )
  1949. {
  1950. DEBUG_PRINT((1, "Permedia2SetColorLookup: invalid parameter\n"));
  1951. return ERROR_INVALID_PARAMETER;
  1952. }
  1953. //
  1954. // Set CLUT registers directly on the hardware.
  1955. //
  1956. switch (hwDeviceExtension->DacId)
  1957. {
  1958. case TVP4020_RAMDAC:
  1959. case P2RD_RAMDAC:
  1960. break;
  1961. default:
  1962. return (ERROR_DEV_NOT_EXIST);
  1963. }
  1964. if (hwDeviceExtension->bVTGRunning &&
  1965. hwDeviceExtension->bMonitorPoweredOn)
  1966. {
  1967. //
  1968. // if VTG has been set-up, we wait for VSync before updating
  1969. // the palette entries (just to avoid possible flickers)
  1970. //
  1971. VsEnd = VideoPortReadRegisterUlong(VS_END);
  1972. while ( VideoPortReadRegisterUlong(LINE_COUNT) > VsEnd );
  1973. }
  1974. //
  1975. // RAMDAC Programming phase
  1976. //
  1977. for ( i = 0, j = ClutBuffer->FirstEntry;
  1978. i < ClutBuffer->NumEntries;
  1979. i++, j++ )
  1980. {
  1981. //
  1982. // Update the RAMDAC entry if it has changed or if we have
  1983. // been told to overwrite it.
  1984. //
  1985. if ( ForceRAMDACWrite ||
  1986. ( LUTCachePtr->LookupTable[j].RgbLong !=
  1987. ClutBuffer->LookupTable[i].RgbLong ) )
  1988. {
  1989. switch (hwDeviceExtension->DacId)
  1990. {
  1991. case TVP4020_RAMDAC:
  1992. TVP4020_LOAD_PALETTE_INDEX (
  1993. j,
  1994. ClutBuffer->LookupTable[i].RgbArray.Red,
  1995. ClutBuffer->LookupTable[i].RgbArray.Green,
  1996. ClutBuffer->LookupTable[i].RgbArray.Blue);
  1997. break;
  1998. case P2RD_RAMDAC:
  1999. P2RD_LOAD_PALETTE_INDEX (
  2000. j,
  2001. ClutBuffer->LookupTable[i].RgbArray.Red,
  2002. ClutBuffer->LookupTable[i].RgbArray.Green,
  2003. ClutBuffer->LookupTable[i].RgbArray.Blue);
  2004. break;
  2005. }
  2006. }
  2007. //
  2008. // Update the cache, if instructed to do so
  2009. //
  2010. if (UpdateCache)
  2011. {
  2012. LUTCachePtr->LookupTable[j].RgbLong = ClutBuffer->LookupTable[i].RgbLong;
  2013. }
  2014. }
  2015. return NO_ERROR;
  2016. } // end Permedia2SetColorLookup()
  2017. VOID
  2018. Permedia2GetClockSpeeds(
  2019. PVOID HwDeviceExtension
  2020. )
  2021. /*++
  2022. Routine Description:
  2023. Work out the chip clock speed and save in hwDeviceExtension.
  2024. Arguments:
  2025. hwDeviceExtension - Supplies a pointer to the miniport's device extension.
  2026. Return Value:
  2027. On return the following values will be in hwDeviceExtension:
  2028. - ChipClockSpeed: this is the desired speed for the chip
  2029. - RefClockSpeed: this is the speed of the oscillator input on the board
  2030. Note:
  2031. We use ChipClockSpeed to refer to the speed of the chip. RefClockSpeed
  2032. is the reference clock speed.
  2033. --*/
  2034. {
  2035. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  2036. ULONG ulValue, ulChipClk, ulRefClk;
  2037. VP_STATUS status;
  2038. P2_DECL;
  2039. //
  2040. // inherit the values from board zero or default
  2041. //
  2042. ulChipClk = hwDeviceExtension->ChipClockSpeed;
  2043. ulRefClk = REF_CLOCK_SPEED;
  2044. //
  2045. // Use the Registry specified clock-speed if supplied
  2046. //
  2047. status = VideoPortGetRegistryParameters( HwDeviceExtension,
  2048. L"PermediaClockSpeed",
  2049. FALSE,
  2050. Permedia2RegistryCallback,
  2051. &ulChipClk);
  2052. if ( (status != NO_ERROR) || ulChipClk == 0)
  2053. {
  2054. //
  2055. // The Registry does not specify an override so read the chip clock
  2056. // speed (in MHz) from the Video ROM BIOS (offset 0xA in the BIOS)
  2057. // NB. this involves changing the aperture 2 register so aperture
  2058. // better be completely idle or we could be in trouble; fortunately
  2059. // we only call this function during a mode change and expect
  2060. // aperture 2 (the FrameBuffer) to be idle
  2061. //
  2062. ULONG Default = VideoPortReadRegisterUlong(APERTURE_TWO);
  2063. UCHAR *p = (UCHAR *)hwDeviceExtension->pFramebuffer;
  2064. //
  2065. // r/w via aperture 2 actually go to ROM
  2066. //
  2067. VideoPortWriteRegisterUlong(APERTURE_TWO, Default | 0x200);
  2068. //
  2069. // If we have a valid ROM then read the clock speed
  2070. //
  2071. if (VideoPortReadRegisterUshort ((USHORT *) p) == 0xAA55)
  2072. {
  2073. //
  2074. // Get the clock speed, on some boards (eg Creative), the clock
  2075. // value at 0x0A is sometimes remains undefined leading to
  2076. // unpredictable results. The values are validated before this
  2077. // function returns
  2078. //
  2079. ulChipClk = VideoPortReadRegisterUchar(&(p[0xA]));
  2080. DEBUG_PRINT((1, "ROM clk speed value 0x%x\n Mhz", ulChipClk));
  2081. }
  2082. else
  2083. {
  2084. DEBUG_PRINT((1, "Bad BIOS ROM header 0x%x\n",
  2085. (ULONG) VideoPortReadRegisterUshort ((USHORT *) p)));
  2086. }
  2087. VideoPortWriteRegisterUlong(APERTURE_TWO, Default);
  2088. }
  2089. //
  2090. // Convert to Hz
  2091. //
  2092. ulChipClk *= 1000000;
  2093. //
  2094. // Validate the selected clock speed, adjust if it is either too
  2095. // high or too low.
  2096. //
  2097. if (ulChipClk < MIN_PERMEDIA_CLOCK_SPEED)
  2098. {
  2099. if(ulChipClk == 0x00)
  2100. {
  2101. ulChipClk = PERMEDIA2_DEFAULT_CLOCK_SPEED;
  2102. }
  2103. else
  2104. {
  2105. ulChipClk = MIN_PERMEDIA_CLOCK_SPEED;
  2106. }
  2107. }
  2108. if (ulChipClk > MAX_PERMEDIA_CLOCK_SPEED)
  2109. {
  2110. DEBUG_PRINT((1, "PERM2: Permedia clock speed %d too fast. Limiting to %d\n" ,
  2111. ulChipClk, MAX_PERMEDIA_CLOCK_SPEED));
  2112. ulChipClk= PERMEDIA2_DEFAULT_CLOCK_SPEED;
  2113. }
  2114. DEBUG_PRINT((3, "PERM2: Permedia Clock Speed set to %dHz\n", ulChipClk));
  2115. hwDeviceExtension->ChipClockSpeed = ulChipClk;
  2116. hwDeviceExtension->RefClockSpeed = ulRefClk;
  2117. }
  2118. VOID
  2119. ZeroMemAndDac(
  2120. PHW_DEVICE_EXTENSION hwDeviceExtension,
  2121. ULONG RequestedMode
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. Initialize the DAC to 0 (black).
  2126. Arguments:
  2127. hwDeviceExtension - Supplies a pointer to the miniport's device extension.
  2128. RequestedMode - use the VIDEO_MODE_NO_ZERO_MEMORY bit to determine if the
  2129. framebuffer should be cleared
  2130. Return Value:
  2131. None
  2132. --*/
  2133. {
  2134. ULONG i;
  2135. P2_DECL;
  2136. TVP4020_DECL;
  2137. P2RD_DECL;
  2138. //
  2139. // Turn off the screen at the DAC.
  2140. //
  2141. if (hwDeviceExtension->DacId == TVP4020_RAMDAC)
  2142. {
  2143. TVP4020_SET_PIXEL_READMASK (0x0);
  2144. TVP4020_PALETTE_START_WR (0);
  2145. for (i = 0; i <= VIDEO_MAX_COLOR_REGISTER; i++)
  2146. {
  2147. TVP4020_LOAD_PALETTE (0, 0, 0);
  2148. }
  2149. }
  2150. else
  2151. {
  2152. P2RD_SET_PIXEL_READMASK (0x0);
  2153. P2RD_PALETTE_START_WR(0);
  2154. for (i = 0; i <= VIDEO_MAX_COLOR_REGISTER; i++)
  2155. {
  2156. P2RD_LOAD_PALETTE (0, 0, 0);
  2157. }
  2158. }
  2159. if (!(RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY))
  2160. {
  2161. //
  2162. // Zero the memory. Don't use Permedia 2 as we would have to save and
  2163. // restore state and that's a pain. This is not time critical.
  2164. //
  2165. VideoPortZeroDeviceMemory(hwDeviceExtension->pFramebuffer,
  2166. hwDeviceExtension->FrameLength);
  2167. DEBUG_PRINT((1, "PERM2: framebuffer cleared\n"));
  2168. }
  2169. //
  2170. // Turn on the screen at the DAC
  2171. //
  2172. if (hwDeviceExtension->DacId == TVP4020_RAMDAC)
  2173. {
  2174. TVP4020_SET_PIXEL_READMASK (0xff);
  2175. }
  2176. else
  2177. {
  2178. P2RD_SET_PIXEL_READMASK (0xff);
  2179. }
  2180. LUT_CACHE_INIT();
  2181. return;
  2182. }
  2183. #if DBG
  2184. VOID
  2185. DumpPCIConfigSpace(
  2186. PVOID HwDeviceExtension,
  2187. ULONG bus,
  2188. ULONG slot)
  2189. {
  2190. PPCI_COMMON_CONFIG PciData;
  2191. UCHAR buffer[sizeof(PCI_COMMON_CONFIG)];
  2192. ULONG j;
  2193. PciData = (PPCI_COMMON_CONFIG)buffer;
  2194. j = VideoPortGetBusData( HwDeviceExtension,
  2195. PCIConfiguration,
  2196. slot,
  2197. PciData,
  2198. 0,
  2199. PCI_COMMON_HDR_LENGTH + 4 );
  2200. //
  2201. // don't report junk slots
  2202. //
  2203. if (PciData->VendorID == 0xffff)
  2204. return;
  2205. DEBUG_PRINT((2, "PERM2: DumpPCIConfigSpace: VideoPortGetBusData returned %d PCI_COMMON_HDR_LENGTH = %d\n",
  2206. j, PCI_COMMON_HDR_LENGTH+4));
  2207. DEBUG_PRINT((2, "DumpPCIConfigSpace: ------------------------\n"));
  2208. DEBUG_PRINT((2, " Bus: %d\n", bus ));
  2209. DEBUG_PRINT((2, " Slot: %d\n", slot ));
  2210. DEBUG_PRINT((2, " Vendor Id: 0x%x\n", PciData->VendorID ));
  2211. DEBUG_PRINT((2, " Device Id: 0x%x\n", PciData->DeviceID ));
  2212. DEBUG_PRINT((2, " Command: 0x%x\n", PciData->Command ));
  2213. DEBUG_PRINT((2, " Status: 0x%x\n", PciData->Status ));
  2214. DEBUG_PRINT((2, " Rev Id: 0x%x\n", PciData->RevisionID ));
  2215. DEBUG_PRINT((2, " ProgIf: 0x%x\n", PciData->ProgIf ));
  2216. DEBUG_PRINT((2, " SubClass: 0x%x\n", PciData->SubClass ));
  2217. DEBUG_PRINT((2, " BaseClass: 0x%x\n", PciData->BaseClass ));
  2218. DEBUG_PRINT((2, " CacheLine: 0x%x\n", PciData->CacheLineSize ));
  2219. DEBUG_PRINT((2, " Latency: 0x%x\n", PciData->LatencyTimer ));
  2220. DEBUG_PRINT((2, " Header Type: 0x%x\n", PciData->HeaderType ));
  2221. DEBUG_PRINT((2, " BIST: 0x%x\n", PciData->BIST ));
  2222. DEBUG_PRINT((2, " Base Reg[0]: 0x%x\n", PciData->u.type0.BaseAddresses[0] ));
  2223. DEBUG_PRINT((2, " Base Reg[1]: 0x%x\n", PciData->u.type0.BaseAddresses[1] ));
  2224. DEBUG_PRINT((2, " Base Reg[2]: 0x%x\n", PciData->u.type0.BaseAddresses[2] ));
  2225. DEBUG_PRINT((2, " Base Reg[3]: 0x%x\n", PciData->u.type0.BaseAddresses[3] ));
  2226. DEBUG_PRINT((2, " Base Reg[4]: 0x%x\n", PciData->u.type0.BaseAddresses[4] ));
  2227. DEBUG_PRINT((2, " Base Reg[5]: 0x%x\n", PciData->u.type0.BaseAddresses[5] ));
  2228. DEBUG_PRINT((2, " Rom Base: 0x%x\n", PciData->u.type0.ROMBaseAddress ));
  2229. DEBUG_PRINT((2, " Interrupt Line: 0x%x\n", PciData->u.type0.InterruptLine ));
  2230. DEBUG_PRINT((2, " Interrupt Pin: 0x%x\n", PciData->u.type0.InterruptPin ));
  2231. DEBUG_PRINT((2, " Min Grant: 0x%x\n", PciData->u.type0.MinimumGrant ));
  2232. DEBUG_PRINT((2, " Max Latency: 0x%x\n", PciData->u.type0.MaximumLatency ));
  2233. DEBUG_PRINT((2, " AGP Capability: 0x%x\n", buffer[0x40]));
  2234. DEBUG_PRINT((2, " AGP Next Cap: 0x%x\n", buffer[0x41]));
  2235. DEBUG_PRINT((2, " AGP Revision: 0x%x\n", buffer[0x42]));
  2236. DEBUG_PRINT((2, " AGP Status: 0x%x\n", buffer[0x43]));
  2237. }
  2238. #endif //DBG