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.

2320 lines
83 KiB

  1. /************************************************************************/
  2. /* */
  3. /* INIT_CX.C */
  4. /* */
  5. /* Nov 15 1993 (c) 1993, ATI Technologies Incorporated. */
  6. /************************************************************************/
  7. /********************** PolyTron RCS Utilities
  8. $Revision: 1.42 $
  9. $Date: 15 May 1996 16:34:38 $
  10. $Author: RWolff $
  11. $Log: S:/source/wnt/ms11/miniport/archive/init_cx.c_v $
  12. *
  13. * Rev 1.42 15 May 1996 16:34:38 RWolff
  14. * Now reports failure of mode set, waits for idle after setting
  15. * accelerator mode.
  16. *
  17. * Rev 1.41 01 May 1996 14:09:20 RWolff
  18. * Calls new routine DenseOnAlpha() to determine dense space support rather
  19. * than assuming all PCI cards support dense space.
  20. *
  21. * Rev 1.40 17 Apr 1996 13:09:04 RWolff
  22. * Backed out Alpha LFB mapping as dense.
  23. *
  24. * Rev 1.39 11 Apr 1996 15:13:20 RWolff
  25. * Now maps framebuffer as dense on DEC Alpha with PCI graphics card.
  26. *
  27. * Rev 1.38 20 Mar 1996 13:42:32 RWolff
  28. * Removed debug print statements from RestoreMemSize_cx(), which must
  29. * be nonpageable since it is called from ATIMPResetHw().
  30. *
  31. * Rev 1.37 01 Mar 1996 12:11:50 RWolff
  32. * VGA Graphics Index and Graphics Data are now handled as separate
  33. * registers rather than as offsets into the block of VGA registers.
  34. *
  35. * Rev 1.36 02 Feb 1996 17:16:40 RWolff
  36. * Now uses VideoPortInt10() rather than our no-BIOS code to set "canned"
  37. * modes on VGA-disabled cards.
  38. *
  39. * Rev 1.35 29 Jan 1996 16:55:02 RWolff
  40. * Now uses VideoPortInt10() rather than no-BIOS code on PPC.
  41. *
  42. * Rev 1.34 23 Jan 1996 11:46:22 RWolff
  43. * Added debug print statements.
  44. *
  45. * Rev 1.33 22 Dec 1995 14:53:30 RWolff
  46. * Added support for Mach 64 GT internal DAC.
  47. *
  48. * Rev 1.32 23 Nov 1995 11:27:46 RWolff
  49. * Fixes needed for initial run of VT chips (check if they're still needed
  50. * on the final version), added support for multiple block-relocatable
  51. * Mach 64 cards.
  52. *
  53. * Rev 1.31 28 Jul 1995 14:40:58 RWolff
  54. * Added support for the Mach 64 VT (CT equivalent with video overlay).
  55. *
  56. * Rev 1.30 23 Jun 1995 16:01:46 RWOLFF
  57. * In 8BPP and lower modes, SetPalette_cx() now uses the VGA palette
  58. * registers rather than the accelerator palette registers. This is
  59. * done so that a video capture card attached to the feature connector
  60. * will know what colours the palette is set to.
  61. *
  62. * Rev 1.29 02 Jun 1995 14:26:48 RWOLFF
  63. * Added debug print statements.
  64. *
  65. * Rev 1.28 31 Mar 1995 11:57:12 RWOLFF
  66. * Changed from all-or-nothing debug print statements to thresholds
  67. * depending on importance of the message.
  68. *
  69. * Rev 1.27 08 Mar 1995 11:33:54 ASHANMUG
  70. * Fixed a bug if the banked aperture was enabled, the memory mapped register we
  71. * getting moved if the memory sized was changed to support 4bpp
  72. *
  73. * Rev 1.26 27 Feb 1995 17:48:08 RWOLFF
  74. * Now always reports 1M when mapping video memory for 4BPP, since we
  75. * force the card to 1M, QueryPublicAccessRanges_cx() now returns
  76. * the virtual address of the I/O register base rather than the
  77. * beginning of I/O space.
  78. *
  79. * Rev 1.25 20 Feb 1995 18:01:18 RWOLFF
  80. * Made test and workaround for screen tearing on 2M boundary DAC-independant,
  81. * 1600x1200 16BPP added to modes that have this tearing.
  82. *
  83. * Rev 1.24 14 Feb 1995 15:45:36 RWOLFF
  84. * Changed conditional compile that uses or fakes failure of
  85. * VideoPortMapBankedMemory() to look for IOCTL_VIDEO_SHARE_VIDEO_MEMORY
  86. * instead of the routine itself. Looking for the routine always failed,
  87. * and since the routine is supplied in order to allow DCI to be used
  88. * on systems without a linear framebuffer, it should be available on
  89. * any DDK version that supports the IOCTL. If it isn't, a compile-time
  90. * error will be generated (unresolved external reference).
  91. *
  92. * Rev 1.23 09 Feb 1995 14:57:36 RWOLFF
  93. * Fix for GX-E IBM DAC screen tearing in 800x600 8BPP.
  94. *
  95. * Rev 1.22 07 Feb 1995 18:24:22 RWOLFF
  96. * Fixed screen trash on return from 4BPP test on CT and 4M Xpression.
  97. * These were the first cards I was able to obtain that switched aperture
  98. * size between modes (GX uses 8M aperture only on 4M cards, which used
  99. * to be made only with DAC that didn't support 4BPP, but CT uses 8M for
  100. * 2M card and 4M when cut back to 1M).
  101. *
  102. * Rev 1.21 03 Feb 1995 15:15:12 RWOLFF
  103. * Added support for DCI, fixed CT internal DAC 4BPP cursor problem,
  104. * RestoreMemSize_cx() is no longer pageable, since it is called
  105. * on a bugcheck.
  106. *
  107. * Rev 1.20 30 Jan 1995 11:56:24 RWOLFF
  108. * Now supports CT internal DAC.
  109. *
  110. * Rev 1.19 11 Jan 1995 14:04:04 RWOLFF
  111. * Added routine RestoreMemSize_cx() which sets the memory size register
  112. * back to the value read by the BIOS query. This is used when returning
  113. * from a test of 4BPP (code had been inlined there) or when shutting down
  114. * from 4BPP (new) because 4BPP modes require that the memory size be
  115. * set to 1M. On some platforms, the x86 emulation in the firmware does not
  116. * reset the memory size to the true value, so a warm reboot from 4BPP left
  117. * the card thinking that it only had 1M.
  118. *
  119. * Rev 1.18 23 Dec 1994 10:47:48 ASHANMUG
  120. * ALPHA/Chrontel-DAC
  121. *
  122. * Rev 1.17 18 Nov 1994 11:40:00 RWOLFF
  123. * Added support for Mach 64 without BIOS.
  124. *
  125. * Rev 1.16 14 Sep 1994 15:24:38 RWOLFF
  126. * Now uses "most desirable supported colour ordering" field in query
  127. * structure rather than DAC type to determine which colour ordering
  128. * to use for 24 and 32BPP.
  129. *
  130. * Rev 1.15 31 Aug 1994 16:24:02 RWOLFF
  131. * Added support for TVP3026 DAC, 1152x864, and BGRx colour ordering
  132. * (used by TVP DAC), uses VideoPort[Read|Write]Register[Uchar|Ushort|Ulong]()
  133. * instead of direct assignments when accessing structures stored in
  134. * VGA text screen off-screen memory.
  135. *
  136. * Rev 1.14 19 Aug 1994 17:15:32 RWOLFF
  137. * Added support for non-standard pixel clock generators.
  138. *
  139. * Rev 1.13 09 Aug 1994 11:52:30 RWOLFF
  140. * Shifting of colours when setting up palette is now done in
  141. * display driver.
  142. *
  143. * Rev 1.12 27 Jun 1994 16:27:38 RWOLFF
  144. * Now reports all hardware default mode tables as noninterlaced to
  145. * avoid confusing the display applet.
  146. *
  147. * Rev 1.11 15 Jun 1994 11:06:24 RWOLFF
  148. * Now sets the cursor colour every time we enter graphics mode. This is a
  149. * fix for the black cursor after testing 4BPP from 16BPP.
  150. *
  151. * Rev 1.10 12 May 1994 11:22:40 RWOLFF
  152. * Added routine SetModeFromTable_cx() to allow the use of refresh rates not
  153. * configured when card was installed, now reports refresh rate from mode table
  154. * instead of only "use hardware default".
  155. *
  156. * Rev 1.9 04 May 1994 10:59:12 RWOLFF
  157. * Now forces memory size to 1M on all 4BPP-capable DACs when using 4BPP,
  158. * sets memory size back to true value when not using 4BPP.
  159. *
  160. * Rev 1.8 27 Apr 1994 13:59:38 RWOLFF
  161. * Added support for paged aperture, fixed cursor colour for 4BPP.
  162. *
  163. * Rev 1.7 26 Apr 1994 12:38:32 RWOLFF
  164. * Now uses a frame length of 128k when LFB is disabled.
  165. *
  166. * Rev 1.6 31 Mar 1994 15:02:42 RWOLFF
  167. * Added SetPowerManagement_cx() function to implement DPMS handling,
  168. * added 4BPP support.
  169. *
  170. * Rev 1.5 14 Mar 1994 16:30:58 RWOLFF
  171. * XMillimeter field of mode information structure now set properly, added
  172. * fix for 2M boundary tearing.
  173. *
  174. * Rev 1.4 03 Mar 1994 12:37:32 ASHANMUG
  175. * Set palettized mode
  176. *
  177. * Rev 1.2 03 Feb 1994 16:44:26 RWOLFF
  178. * Fixed "ceiling check" on right scissor register (documentation had
  179. * maximum value wrong). Moved initialization of hardware cursor
  180. * colours to after the switch into graphics mode. Colour initialization
  181. * is ignored if it is done before the mode switch (undocumented), but
  182. * this wasn't noticed earlier because most cards power up with the
  183. * colours already set to the values we want.
  184. *
  185. * Rev 1.1 31 Jan 1994 16:24:38 RWOLFF
  186. * Fixed setting of cursor colours on cards with 68860 DAC, now fills
  187. * in Frequency and VideoMemoryBitmap[Width|Height] fields of mode
  188. * information structure. Sets Number[Red|Green|Blue]Bits fields for
  189. * palette modes to 6 (assumes VGA-compatible DAC) instead of 0 to allow
  190. * Windows NT to set the palette colours to the best match for the
  191. * colours to be displayed.
  192. *
  193. * Rev 1.0 31 Jan 1994 11:10:18 RWOLFF
  194. * Initial revision.
  195. *
  196. * Rev 1.3 24 Jan 1994 18:03:52 RWOLFF
  197. * Changes to accomodate 94/01/19 BIOS document.
  198. *
  199. * Rev 1.2 14 Jan 1994 15:20:48 RWOLFF
  200. * Fixes required by BIOS version 0.13, added 1600x1200 support.
  201. *
  202. * Rev 1.1 15 Dec 1993 15:26:30 RWOLFF
  203. * Clear screen only the first time we set the desired video mode.
  204. *
  205. * Rev 1.0 30 Nov 1993 18:32:22 RWOLFF
  206. * Initial revision.
  207. End of PolyTron RCS section *****************/
  208. #ifdef DOC
  209. INIT_CX.C - Highest-level card-dependent routines for miniport.
  210. DESCRIPTION
  211. This file contains initialization and packet handling routines
  212. for Mach 64-compatible ATI accelerators. Routines in this module
  213. are called only by routines in ATIMP.C, which is card-independent.
  214. OTHER FILES
  215. #endif
  216. #include "dderror.h"
  217. #include "miniport.h"
  218. #include "ntddvdeo.h"
  219. #include "video.h"
  220. #include "stdtyp.h"
  221. #include "amachcx.h"
  222. #include "amach1.h"
  223. #include "atimp.h"
  224. #include "atint.h"
  225. #define INCLUDE_INIT_CX
  226. #include "init_cx.h"
  227. #include "query_cx.h"
  228. #include "services.h"
  229. #include "setup_cx.h"
  230. /*
  231. * Prototypes for static functions.
  232. */
  233. static void QuerySingleMode_cx(PVIDEO_MODE_INFORMATION ModeInformation, struct query_structure *QueryPtr, ULONG ModeIndex);
  234. static VP_STATUS SetModeFromTable_cx(struct st_mode_table *ModeTable, VIDEO_X86_BIOS_ARGUMENTS Registers);
  235. /*
  236. * Allow miniport to be swapped out when not needed.
  237. */
  238. #if defined (ALLOC_PRAGMA)
  239. #pragma alloc_text(PAGE_CX, Initialize_cx)
  240. #pragma alloc_text(PAGE_CX, MapVideoMemory_cx)
  241. #pragma alloc_text(PAGE_CX, QueryPublicAccessRanges_cx)
  242. #pragma alloc_text(PAGE_CX, QueryCurrentMode_cx)
  243. #pragma alloc_text(PAGE_CX, QueryAvailModes_cx)
  244. #pragma alloc_text(PAGE_CX, QuerySingleMode_cx)
  245. #pragma alloc_text(PAGE_CX, SetCurrentMode_cx)
  246. #pragma alloc_text(PAGE_CX, SetPalette_cx)
  247. #pragma alloc_text(PAGE_CX, IdentityMapPalette_cx)
  248. #pragma alloc_text(PAGE_CX, ResetDevice_cx)
  249. #pragma alloc_text(PAGE_CX, SetPowerManagement_cx)
  250. #pragma alloc_text(PAGE_CX, GetPowerManagement_cx)
  251. #pragma alloc_text(PAGE_CX, SetModeFromTable_cx)
  252. /* RestoreMemSize_cx() can't be made pageable */
  253. #pragma alloc_text(PAGE_CX, ShareVideoMemory_cx)
  254. /* BankMap_cx() can't be made pageable */
  255. #endif
  256. /***************************************************************************
  257. *
  258. * void Initialize_cx(void);
  259. *
  260. * DESCRIPTION:
  261. * This routine is the Mach 64-compatible hardware initialization routine
  262. * for the miniport driver. It is called once an adapter has been found
  263. * and all the required data structures for it have been created.
  264. *
  265. * GLOBALS CHANGED:
  266. * none
  267. *
  268. * CALLED BY:
  269. * ATIMPInitialize()
  270. *
  271. * AUTHOR:
  272. * Robert Wolff
  273. *
  274. * CHANGE HISTORY:
  275. *
  276. * TEST HISTORY:
  277. *
  278. ***************************************************************************/
  279. void Initialize_cx(void)
  280. {
  281. DWORD Scratch; /* Temporary variable */
  282. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  283. struct query_structure *Query; /* Information about the graphics card */
  284. Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
  285. /*
  286. * If the linear aperture is not configured, enable the VGA aperture.
  287. */
  288. if (phwDeviceExtension->FrameLength == 0)
  289. {
  290. VideoDebugPrint((DEBUG_DETAIL, "Initialize_cx() switching to VGA aperture\n"));
  291. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  292. Registers.Eax = BIOS_APERTURE;
  293. Registers.Ecx = BIOS_VGA_APERTURE;
  294. VideoPortInt10(phwDeviceExtension, &Registers);
  295. }
  296. /*
  297. * Set the screen to start at the beginning of accelerator memory.
  298. */
  299. Scratch = INPD(CRTC_OFF_PITCH) & ~CRTC_OFF_PITCH_Offset;
  300. OUTPD(CRTC_OFF_PITCH, Scratch);
  301. /*
  302. * Disable the hardware cursor and set it up with the bitmap
  303. * starting at the top left corner of the 64x64 block.
  304. */
  305. Scratch = INPD(GEN_TEST_CNTL) & ~GEN_TEST_CNTL_CursorEna;
  306. OUTPD(GEN_TEST_CNTL, Scratch);
  307. OUTPD(CUR_HORZ_VERT_OFF, 0x00000000);
  308. /*
  309. * TVP3026 DAC requires special handling to disable
  310. * the cursor.
  311. */
  312. if (Query->q_DAC_type == DAC_TVP3026)
  313. {
  314. /*
  315. * Access the indirect cursor control register.
  316. */
  317. OUTP(DAC_CNTL, (BYTE)(INP(DAC_CNTL) & 0xFC));
  318. OUTP(DAC_REGS, 6);
  319. /*
  320. * Write the "cursor disabled" value to the
  321. * indexed data register.
  322. */
  323. OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC) | 2));
  324. OUTP_HBLW(DAC_REGS, 0);
  325. /*
  326. * Go back to using direct registers.
  327. */
  328. OUTP(DAC_CNTL, (BYTE)(INP(DAC_CNTL) & 0xFC));
  329. }
  330. VideoDebugPrint((DEBUG_NORMAL, "Initialize_cx() complete\n"));
  331. return;
  332. } /* Initialize_cx() */
  333. /**************************************************************************
  334. *
  335. * VP_STATUS MapVideoMemory_cx(RequestPacket, QueryPtr);
  336. *
  337. * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
  338. * struct query_structure *QueryPtr; Query information for the card
  339. *
  340. * DESCRIPTION:
  341. * Map the card's video memory into system memory and store the mapped
  342. * address and size in OutputBuffer.
  343. *
  344. * RETURN VALUE:
  345. * NO_ERROR if successful
  346. * error code if failed
  347. *
  348. * GLOBALS CHANGED:
  349. * FrameLength and PhysicalFrameAddress fields of phwDeviceExtension
  350. * if linear framebuffer is not present.
  351. *
  352. * CALLED BY:
  353. * IOCTL_VIDEO_MAP_VIDEO_MEMORY packet of ATIMPStartIO()
  354. *
  355. * AUTHOR:
  356. * Robert Wolff
  357. *
  358. * CHANGE HISTORY:
  359. *
  360. * TEST HISTORY:
  361. *
  362. ***************************************************************************/
  363. VP_STATUS MapVideoMemory_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
  364. {
  365. PVIDEO_MEMORY_INFORMATION memoryInformation;
  366. ULONG inIoSpace; /* Scratch variable used by VideoPortMapMemory() */
  367. VP_STATUS status; /* Error code obtained from O/S calls */
  368. UCHAR Scratch; /* Temporary variable */
  369. ULONG FrameBufferLengthSave;
  370. memoryInformation = RequestPacket->OutputBuffer;
  371. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  372. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  373. /*
  374. * The VideoRamLength field contains the amount of video memory
  375. * on the card. The FrameBufferLength field contains the
  376. * size of the aperture in bytes
  377. *
  378. * Initially assume that the linear aperture is available.
  379. *
  380. * In 4BPP, we always force the card to think it has 1M of memory.
  381. */
  382. if (QueryPtr->q_pix_depth == 4)
  383. memoryInformation->VideoRamLength = ONE_MEG;
  384. else
  385. memoryInformation->VideoRamLength = phwDeviceExtension->VideoRamSize;
  386. Scratch = QueryPtr->q_aperture_cfg & CONFIG_CNTL_LinApMask;
  387. if (Scratch == CONFIG_CNTL_LinAp4M)
  388. {
  389. memoryInformation->FrameBufferLength = 4 * ONE_MEG;
  390. }
  391. else if (Scratch == CONFIG_CNTL_LinAp8M)
  392. {
  393. memoryInformation->FrameBufferLength = 8 * ONE_MEG;
  394. }
  395. /*
  396. * If the linear aperture is not available, map in the VGA aperture
  397. * instead. Since the Mach 64 needs an aperture in order to use
  398. * the drawing registers, ATIMPFindAdapter() will have already
  399. * reported that it couldn't find a usable card if both the linear
  400. * and VGA apertures are disabled.
  401. */
  402. else if (Scratch == CONFIG_CNTL_LinApDisab)
  403. {
  404. phwDeviceExtension->FrameLength = 0x20000;
  405. phwDeviceExtension->PhysicalFrameAddress.LowPart = 0x0A0000;
  406. memoryInformation->FrameBufferLength = phwDeviceExtension->FrameLength;
  407. }
  408. inIoSpace = 0;
  409. #if defined(ALPHA)
  410. /*
  411. * Use dense space if we can, otherwise use sparse space.
  412. */
  413. if (DenseOnAlpha(QueryPtr) == TRUE)
  414. {
  415. VideoDebugPrint((DEBUG_DETAIL, "Using dense space for LFB\n"));
  416. inIoSpace = 4;
  417. }
  418. #endif
  419. FrameBufferLengthSave = memoryInformation->FrameBufferLength;
  420. status = VideoPortMapMemory(phwDeviceExtension,
  421. phwDeviceExtension->PhysicalFrameAddress,
  422. &(memoryInformation->FrameBufferLength),
  423. &inIoSpace,
  424. &(memoryInformation->VideoRamBase));
  425. #if defined (ALPHA)
  426. /*
  427. * VideoPortMapMemory() returns invalid FrameBufferLength
  428. * on the Alpha.
  429. */
  430. memoryInformation->FrameBufferLength = FrameBufferLengthSave;
  431. #endif
  432. memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
  433. VideoDebugPrint((DEBUG_DETAIL, "Frame buffer mapped base = 0x%X\n", memoryInformation->VideoRamBase));
  434. /*
  435. * On some DAC/memory combinations, some modes which require more
  436. * than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
  437. * 1600x1200 16BPP) will have screen tearing at the 2M boundary.
  438. *
  439. * As a workaround, the display driver must start the framebuffer
  440. * at an offset which will put the 2M boundary at the start of a
  441. * scanline.
  442. *
  443. * Other DAC/memory combinations are unaffected, but since this
  444. * fix is nearly harmless (only ill effect is to make DCI unusable
  445. * in these modes), we can catch all future combinations which
  446. * suffer from this problem by assuming that all DAC/memory
  447. * combinations are affected.
  448. */
  449. if ((QueryPtr->q_pix_depth == 24) &&
  450. (QueryPtr->q_desire_x == 1280))
  451. (PUCHAR)memoryInformation->FrameBufferBase += (0x40 * 8);
  452. else if ((QueryPtr->q_pix_depth == 24) &&
  453. (QueryPtr->q_desire_x == 1152))
  454. (PUCHAR)memoryInformation->FrameBufferBase += (0x160 * 8);
  455. else if ((QueryPtr->q_pix_depth == 16) &&
  456. (QueryPtr->q_desire_x == 1600))
  457. (PUCHAR)memoryInformation->FrameBufferBase += (0x90 * 8);
  458. return status;
  459. } /* MapVideoMemory_cx() */
  460. /**************************************************************************
  461. *
  462. * VP_STATUS QueryPublicAccessRanges_cx(RequestPacket);
  463. *
  464. * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
  465. *
  466. * DESCRIPTION:
  467. * Map and return information on the video card's public access ranges.
  468. *
  469. * RETURN VALUE:
  470. * NO_ERROR if successful
  471. * error code if failed
  472. *
  473. * GLOBALS CHANGED:
  474. * none
  475. *
  476. * CALLED BY:
  477. * IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES packet of ATIMPStartIO()
  478. *
  479. * AUTHOR:
  480. * Robert Wolff
  481. *
  482. * CHANGE HISTORY:
  483. *
  484. * TEST HISTORY:
  485. *
  486. ***************************************************************************/
  487. VP_STATUS QueryPublicAccessRanges_cx(PVIDEO_REQUEST_PACKET RequestPacket)
  488. {
  489. PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
  490. PHYSICAL_ADDRESS physicalPortBase;
  491. ULONG physicalPortLength;
  492. if ( RequestPacket->OutputBufferLength <
  493. (RequestPacket->StatusBlock->Information =
  494. sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) )
  495. {
  496. VideoDebugPrint((DEBUG_ERROR, "QueryPublicAccessRanges_cx() - buffer too small to handle query\n"));
  497. return ERROR_INSUFFICIENT_BUFFER;
  498. }
  499. portAccess = RequestPacket->OutputBuffer;
  500. portAccess->VirtualAddress = (PVOID) NULL; // Requested VA
  501. portAccess->InIoSpace = 1; // In IO space
  502. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  503. physicalPortBase.HighPart = 0x00000000;
  504. physicalPortBase.LowPart = GetIOBase_cx();
  505. // physicalPortLength = LINEDRAW+2 - physicalPortBase.LowPart;
  506. /*
  507. * If we are using packed (relocatable) I/O, all our I/O mapped
  508. * registers are in a 1k block. If not, they are sparsely distributed
  509. * in a 32k region.
  510. */
  511. if (IsPackedIO_cx())
  512. physicalPortLength = 0x400;
  513. else
  514. physicalPortLength = 0x8000;
  515. // *SANITIZE* Should report MM registers instead
  516. return VideoPortMapMemory(phwDeviceExtension,
  517. physicalPortBase,
  518. &physicalPortLength,
  519. &(portAccess->MappedInIoSpace),
  520. &(portAccess->VirtualAddress));
  521. } /* QueryPublicAccessRanges_cx() */
  522. /**************************************************************************
  523. *
  524. * VP_STATUS QueryCurrentMode_cx(RequestPacket, QueryPtr);
  525. *
  526. * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
  527. * struct query_structure *QueryPtr; Query information for the card
  528. *
  529. * DESCRIPTION:
  530. * Get screen information and colour masks for the current video mode.
  531. *
  532. * RETURN VALUE:
  533. * NO_ERROR if successful
  534. * error code if failed
  535. *
  536. * GLOBALS CHANGED:
  537. * none
  538. *
  539. * CALLED BY:
  540. * IOCTL_VIDEO_QUERY_CURRENT_MODE packet of ATIMPStartIO()
  541. *
  542. * AUTHOR:
  543. * Robert Wolff
  544. *
  545. * CHANGE HISTORY:
  546. *
  547. * TEST HISTORY:
  548. *
  549. ***************************************************************************/
  550. VP_STATUS QueryCurrentMode_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
  551. {
  552. PVIDEO_MODE_INFORMATION ModeInformation;
  553. /*
  554. * If the output buffer is too small to hold the information we need
  555. * to put in it, return with the appropriate error code.
  556. */
  557. if (RequestPacket->OutputBufferLength <
  558. (RequestPacket->StatusBlock->Information =
  559. sizeof(VIDEO_MODE_INFORMATION)) )
  560. {
  561. VideoDebugPrint((DEBUG_ERROR, "QueryCurrentMode_cx() - buffer too small to handle query\n"));
  562. return ERROR_INSUFFICIENT_BUFFER;
  563. }
  564. /*
  565. * Fill in the mode information structure.
  566. */
  567. ModeInformation = RequestPacket->OutputBuffer;
  568. QuerySingleMode_cx(ModeInformation, QueryPtr, phwDeviceExtension->ModeIndex);
  569. return NO_ERROR;
  570. } /* QueryCurrentMode_cx() */
  571. /**************************************************************************
  572. *
  573. * VP_STATUS QueryAvailModes_cx(RequestPacket, QueryPtr);
  574. *
  575. * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
  576. * struct query_structure *QueryPtr; Query information for the card
  577. *
  578. * DESCRIPTION:
  579. * Get screen information and colour masks for all available video modes.
  580. *
  581. * RETURN VALUE:
  582. * NO_ERROR if successful
  583. * error code if failed
  584. *
  585. * GLOBALS CHANGED:
  586. * none
  587. *
  588. * CALLED BY:
  589. * IOCTL_VIDEO_QUERY_AVAIL_MODES packet of ATIMPStartIO()
  590. *
  591. * AUTHOR:
  592. * Robert Wolff
  593. *
  594. * CHANGE HISTORY:
  595. *
  596. * TEST HISTORY:
  597. *
  598. ***************************************************************************/
  599. VP_STATUS QueryAvailModes_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
  600. {
  601. PVIDEO_MODE_INFORMATION ModeInformation;
  602. ULONG CurrentMode;
  603. /*
  604. * If the output buffer is too small to hold the information we need
  605. * to put in it, return with the appropriate error code.
  606. */
  607. if (RequestPacket->OutputBufferLength <
  608. (RequestPacket->StatusBlock->Information =
  609. QueryPtr->q_number_modes * sizeof(VIDEO_MODE_INFORMATION)) )
  610. {
  611. VideoDebugPrint((DEBUG_ERROR, "QueryAvailModes_cx() - buffer too small to handle query\n"));
  612. return ERROR_INSUFFICIENT_BUFFER;
  613. }
  614. /*
  615. * Fill in the mode information structure.
  616. */
  617. ModeInformation = RequestPacket->OutputBuffer;
  618. /*
  619. * For each mode supported by the card, store the mode characteristics
  620. * in the output buffer.
  621. */
  622. for (CurrentMode = 0; CurrentMode < QueryPtr->q_number_modes; CurrentMode++, ModeInformation++)
  623. QuerySingleMode_cx(ModeInformation, QueryPtr, CurrentMode);
  624. return NO_ERROR;
  625. } /* QueryCurrentMode_cx() */
  626. /**************************************************************************
  627. *
  628. * static void QuerySingleMode_cx(ModeInformation, QueryPtr, ModeIndex);
  629. *
  630. * PVIDEO_MODE_INFORMATION ModeInformation; Table to be filled in
  631. * struct query_structure *QueryPtr; Query information for the card
  632. * ULONG ModeIndex; Index of mode table to use
  633. *
  634. * DESCRIPTION:
  635. * Fill in a single Windows NT mode information table using data from
  636. * one of our CRT parameter tables.
  637. *
  638. * GLOBALS CHANGED:
  639. * none
  640. *
  641. * CALLED BY:
  642. * QueryCurrentMode_cx() and QueryAvailModes_cx()
  643. *
  644. * AUTHOR:
  645. * Robert Wolff
  646. *
  647. * CHANGE HISTORY:
  648. *
  649. * TEST HISTORY:
  650. *
  651. ***************************************************************************/
  652. static void QuerySingleMode_cx(PVIDEO_MODE_INFORMATION ModeInformation,
  653. struct query_structure *QueryPtr,
  654. ULONG ModeIndex)
  655. {
  656. struct st_mode_table *CrtTable; /* Pointer to current mode table */
  657. CrtTable = (struct st_mode_table *)QueryPtr;
  658. ((struct query_structure *)CrtTable)++;
  659. CrtTable += ModeIndex;
  660. ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION);
  661. ModeInformation->ModeIndex = ModeIndex;
  662. ModeInformation->VisScreenWidth = CrtTable->m_x_size;
  663. ModeInformation->VisScreenHeight = CrtTable->m_y_size;
  664. // * Bytes per line = ((pixels/line) * (bits/pixel)) / (bits/byte))
  665. ModeInformation->ScreenStride = (CrtTable->m_screen_pitch * CrtTable->m_pixel_depth) / 8;
  666. ModeInformation->NumberOfPlanes = 1;
  667. ModeInformation->BitsPerPlane = (USHORT) CrtTable->m_pixel_depth;
  668. ModeInformation->Frequency = CrtTable->Refresh;
  669. /*
  670. * Driver can't measure the screen size,
  671. * so take reasonable values (16" diagonal).
  672. */
  673. ModeInformation->XMillimeter = 320;
  674. ModeInformation->YMillimeter = 240;
  675. switch(ModeInformation->BitsPerPlane)
  676. {
  677. case 4:
  678. /*
  679. * Assume 6 bit DAC, since all VGA-compatible DACs support
  680. * 6 bit mode. Future expansion (extensive testing needed):
  681. * check DAC definition to see if 8 bit mode is supported,
  682. * and use 8 bit mode if available.
  683. */
  684. ModeInformation->RedMask = 0x00000000;
  685. ModeInformation->GreenMask = 0x00000000;
  686. ModeInformation->BlueMask = 0x00000000;
  687. ModeInformation->NumberRedBits = 6;
  688. ModeInformation->NumberGreenBits = 6;
  689. ModeInformation->NumberBlueBits = 6;
  690. CrtTable->ColourDepthInfo = BIOS_DEPTH_4BPP;
  691. break;
  692. case 16:
  693. /*
  694. * Assume that all DACs capable of 16BPP support 565.
  695. */
  696. ModeInformation->RedMask = 0x0000f800;
  697. ModeInformation->GreenMask = 0x000007e0;
  698. ModeInformation->BlueMask = 0x0000001f;
  699. ModeInformation->NumberRedBits = 5;
  700. ModeInformation->NumberGreenBits = 6;
  701. ModeInformation->NumberBlueBits = 5;
  702. CrtTable->ColourDepthInfo = BIOS_DEPTH_16BPP_565;
  703. break;
  704. case 24:
  705. /*
  706. * Windows NT uses RGB as the standard 24BPP mode,
  707. * so use this ordering unless this card only
  708. * supports BGR.
  709. */
  710. if (QueryPtr->q_HiColourSupport & RGB24_RGB)
  711. {
  712. ModeInformation->RedMask = 0x00ff0000;
  713. ModeInformation->GreenMask = 0x0000ff00;
  714. ModeInformation->BlueMask = 0x000000ff;
  715. }
  716. else{
  717. ModeInformation->RedMask = 0x000000ff;
  718. ModeInformation->GreenMask = 0x0000ff00;
  719. ModeInformation->BlueMask = 0x00ff0000;
  720. }
  721. CrtTable->ColourDepthInfo = BIOS_DEPTH_24BPP;
  722. ModeInformation->NumberRedBits = 8;
  723. ModeInformation->NumberGreenBits = 8;
  724. ModeInformation->NumberBlueBits = 8;
  725. break;
  726. case 32:
  727. /*
  728. * Windows NT uses RGBx as the standard 32BPP mode,
  729. * so use this ordering if it's available. If it
  730. * isn't, use the best available colour ordering.
  731. */
  732. if (QueryPtr->q_HiColourSupport & RGB32_RGBx)
  733. {
  734. ModeInformation->RedMask = 0xff000000;
  735. ModeInformation->GreenMask = 0x00ff0000;
  736. ModeInformation->BlueMask = 0x0000ff00;
  737. CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_RGBx;
  738. }
  739. else if (QueryPtr->q_HiColourSupport & RGB32_xRGB)
  740. {
  741. ModeInformation->RedMask = 0x00ff0000;
  742. ModeInformation->GreenMask = 0x0000ff00;
  743. ModeInformation->BlueMask = 0x000000ff;
  744. CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_xRGB;
  745. }
  746. else if (QueryPtr->q_HiColourSupport & RGB32_BGRx)
  747. {
  748. ModeInformation->RedMask = 0x0000ff00;
  749. ModeInformation->GreenMask = 0x00ff0000;
  750. ModeInformation->BlueMask = 0xff000000;
  751. CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_BGRx;
  752. }
  753. else /* if (QueryPtr->q_HiColourSupport & RGB32_xBGR) */
  754. {
  755. ModeInformation->RedMask = 0x000000ff;
  756. ModeInformation->GreenMask = 0x0000ff00;
  757. ModeInformation->BlueMask = 0x00ff0000;
  758. CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_xBGR;
  759. }
  760. ModeInformation->NumberRedBits = 8;
  761. ModeInformation->NumberGreenBits = 8;
  762. ModeInformation->NumberBlueBits = 8;
  763. break;
  764. case 8:
  765. default:
  766. /*
  767. * Assume 6 bit DAC, since all VGA-compatible DACs support
  768. * 6 bit mode. Future expansion (extensive testing needed):
  769. * check DAC definition to see if 8 bit mode is supported,
  770. * and use 8 bit mode if available.
  771. */
  772. ModeInformation->RedMask = 0x00000000;
  773. ModeInformation->GreenMask = 0x00000000;
  774. ModeInformation->BlueMask = 0x00000000;
  775. ModeInformation->NumberRedBits = 6;
  776. ModeInformation->NumberGreenBits = 6;
  777. ModeInformation->NumberBlueBits = 6;
  778. CrtTable->ColourDepthInfo = BIOS_DEPTH_8BPP;
  779. break;
  780. }
  781. ModeInformation->AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
  782. if (CrtTable->m_pixel_depth <= 8)
  783. {
  784. ModeInformation->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN |
  785. VIDEO_MODE_MANAGED_PALETTE;
  786. }
  787. /*
  788. * On "canned" mode tables,bit 4 of the m_disp_cntl field is set
  789. * for interlaced modes and cleared for noninterlaced modes.
  790. *
  791. * The display applet gets confused if some of the "Use hardware
  792. * default" modes are interlaced and some are noninterlaced
  793. * (two "Use hardware default" entries are shown in the refresh
  794. * rate list). To avoid this, report all mode tables stored in
  795. * the EEPROM as noninterlaced, even if they are interlaced.
  796. * "Canned" mode tables give true reports.
  797. *
  798. * If the display applet ever gets fixed, configured mode tables
  799. * have (CrtTable->control & (CRTC_GEN_CNTL_Interlace << 8)) nonzero
  800. * for interlaced and zero for noninterlaced.
  801. */
  802. if (CrtTable->Refresh == DEFAULT_REFRESH)
  803. {
  804. ModeInformation->AttributeFlags &= ~VIDEO_MODE_INTERLACED;
  805. }
  806. else
  807. {
  808. if (CrtTable->m_disp_cntl & 0x010)
  809. {
  810. ModeInformation->AttributeFlags |= VIDEO_MODE_INTERLACED;
  811. }
  812. else
  813. {
  814. ModeInformation->AttributeFlags &= ~VIDEO_MODE_INTERLACED;
  815. }
  816. }
  817. /*
  818. * Fill in the video memory bitmap width and height fields.
  819. * The descriptions are somewhat ambiguous - assume that
  820. * "bitmap width" is the same as ScreenStride (bytes from
  821. * start of one scanline to start of the next) and "bitmap
  822. * height" refers to the number of complete scanlines which
  823. * will fit into video memory.
  824. */
  825. ModeInformation->VideoMemoryBitmapWidth = ModeInformation->ScreenStride;
  826. ModeInformation->VideoMemoryBitmapHeight = (QueryPtr->q_memory_size * QUARTER_MEG) / ModeInformation->VideoMemoryBitmapWidth;
  827. return;
  828. } /* QuerySingleMode_m() */
  829. VOID
  830. EnableOldMach64MouseCursor(
  831. PHW_DEVICE_EXTENSION pHwDeviceExtension
  832. )
  833. {
  834. ULONG temp;
  835. VideoDebugPrint((1, "Enabling the cursor\n"));
  836. temp = INPD(GEN_TEST_CNTL);
  837. temp |= GEN_TEST_CNTL_CursorEna;
  838. OUTPD(GEN_TEST_CNTL, temp);
  839. }
  840. /**************************************************************************
  841. *
  842. * VP_STATUS SetCurrentMode_cx(QueryPtr, CrtTable);
  843. *
  844. * struct query_structure *QueryPtr; Query information for the card
  845. * struct st_mode_table *CrtTable; CRT parameter table for desired mode
  846. *
  847. * DESCRIPTION:
  848. * Switch into the specified video mode.
  849. *
  850. * RETURN VALUE:
  851. * NO_ERROR if successful
  852. * error code if failed
  853. *
  854. * NOTE:
  855. * In the event of an error return by one of the services we call,
  856. * there is no indication in our error return of which service failed,
  857. * only the fact that one failed and the error code it returned. If
  858. * a checked version of the miniport is being run under the kernel
  859. * debugger, an indication will be printed to the debug terminal.
  860. *
  861. * GLOBALS CHANGED:
  862. * none
  863. *
  864. * CALLED BY:
  865. * IOCTL_VIDEO_SET_CURRENT_MODE packet of ATIMPStartIO()
  866. *
  867. * AUTHOR:
  868. * Robert Wolff
  869. *
  870. * CHANGE HISTORY:
  871. * 96 05 15 Now checks return values from INT 10 calls.
  872. *
  873. * TEST HISTORY:
  874. *
  875. ***************************************************************************/
  876. VP_STATUS SetCurrentMode_cx(struct query_structure *QueryPtr, struct st_mode_table *CrtTable)
  877. {
  878. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  879. ULONG WidthToClear; /* Screen width (in pixels) to clear */
  880. ULONG ScreenPitch; /* Pitch in units of 8 pixels */
  881. ULONG ScreenOffset = 0; /* Byte offset - varies with display mode */
  882. ULONG PixelDepth; /* Colour depth of screen */
  883. ULONG HorScissors; /* Horizontal scissor values */
  884. ULONG Scratch; /* Temporary variable */
  885. int CursorProgOffset; /* Offset of DAC register used to program the cursor */
  886. VP_STATUS RetVal; /* Value returned by routines called */
  887. /*
  888. * Early versions of the Mach 64 BIOS have a bug where not all registers
  889. * are set when initializing an accelerator mode. These registers are
  890. * set when going into the 640x480 8BPP VGAWonder mode.
  891. *
  892. * All VGA disabled cards were built after this bug was fixed, so
  893. * this mode switch is not necessary for them. On these cards, we
  894. * must not do the mode switch, since it will affect the VGA enabled
  895. * card rather than the card we are working on.
  896. */
  897. if (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB)
  898. {
  899. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  900. Registers.Eax = 0x62;
  901. RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
  902. if (RetVal != NO_ERROR)
  903. {
  904. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed SVGA mode set\n"));
  905. return RetVal;
  906. }
  907. }
  908. /*
  909. * Setting the linear aperture using the BIOS call will set
  910. * a 4M aperture on 2M and lower cards, and an 8M aperture
  911. * on 4M cards. Since we force the memory size to 1M in
  912. * 4BPP modes (workaround for a hardware bug), this can
  913. * result in writing to the wrong location for memory mapped
  914. * registers if we switch between 4BPP and other depths
  915. * (typically when testing a new mode) on a 4M card.
  916. *
  917. * To avoid this, set the memory size to its "honest" value
  918. * before enabling the linear aperture. If we need to cut
  919. * back to 1M, we will do this after the aperture is set.
  920. * This will result in the aperture always being the same
  921. * size, so the memory mapped registers will always be
  922. * in the same place.
  923. *
  924. * When using the VGA aperture, we must set the "honest" value
  925. * after enabling the aperture but before setting the mode.
  926. * Otherwise, the system will hang when testing a mode that
  927. * needs more than 1M of memory from a 4BPP mode.
  928. *
  929. * If the linear aperture is not configured, enable the VGA aperture.
  930. */
  931. if (QueryPtr->q_aperture_cfg != 0)
  932. {
  933. RestoreMemSize_cx();
  934. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  935. Registers.Eax = BIOS_APERTURE;
  936. Registers.Ecx = BIOS_LINEAR_APERTURE;
  937. RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
  938. if (RetVal != NO_ERROR)
  939. {
  940. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed to enable linear aperture\n"));
  941. return RetVal;
  942. }
  943. }
  944. else
  945. {
  946. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  947. Registers.Eax = BIOS_APERTURE;
  948. Registers.Ecx = BIOS_VGA_APERTURE;
  949. RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
  950. if (RetVal != NO_ERROR)
  951. {
  952. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed to enable VGA aperture\n"));
  953. return RetVal;
  954. }
  955. OUTP(VGA_GRAX_IND, 6);
  956. OUTP(VGA_GRAX_DATA, (BYTE)(INP(VGA_GRAX_DATA) & 0xF3));
  957. }
  958. /*
  959. * Now we can set the accelerator mode.
  960. */
  961. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  962. Registers.Eax = BIOS_LOAD_SET;
  963. /*
  964. * ECX register holds colour depth, gamma correction enable/disable
  965. * (not used in NT miniport), pitch size, and resolution.
  966. */
  967. Registers.Ecx = CrtTable->ColourDepthInfo;
  968. /*
  969. * Screen pitch differs from horizontal resolution only when using the
  970. * VGA aperture and horizontal resolution is less than 1024.
  971. */
  972. if ((CrtTable->m_screen_pitch == 1024) && (CrtTable->m_x_size < 1024))
  973. Registers.Ecx |= BIOS_PITCH_1024;
  974. else
  975. Registers.Ecx |= BIOS_PITCH_HOR_RES;
  976. /*
  977. * On the 68860 DAC and ?T internal DACs, we must enable gamma
  978. * correction for all pixel depths where the palette is not used.
  979. */
  980. if (((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
  981. (QueryPtr->q_DAC_type == DAC_INTERNAL_CT) ||
  982. (QueryPtr->q_DAC_type == DAC_INTERNAL_GT) ||
  983. (QueryPtr->q_DAC_type == DAC_INTERNAL_VT)) &&
  984. (QueryPtr->q_pix_depth > 8))
  985. {
  986. Registers.Ecx |= BIOS_ENABLE_GAMMA;
  987. }
  988. /*
  989. * Fix 4bpp bugs by setting memory size to 1Meg. We do not
  990. * need to switch back to the "honest" memory size for
  991. * other pixel depths unless we are using the VGA aperture,
  992. * since this was done for linear apertures before we enabled
  993. * the aperture in order to ensure the same aperture size
  994. * (and therefore the same locations for memory mapped
  995. * registers) is used for all modes.
  996. */
  997. else if (QueryPtr->q_pix_depth == 4)
  998. {
  999. OUTPD(MEM_CNTL, (INPD(MEM_CNTL) & ~MEM_CNTL_MemSizeMsk) | MEM_CNTL_MemSize1Mb);
  1000. }
  1001. else if (QueryPtr->q_aperture_cfg == 0)
  1002. {
  1003. RestoreMemSize_cx();
  1004. }
  1005. switch(CrtTable->m_x_size)
  1006. {
  1007. case 640:
  1008. Registers.Ecx |= BIOS_RES_640x480;
  1009. break;
  1010. case 800:
  1011. Registers.Ecx |= BIOS_RES_800x600;
  1012. break;
  1013. case 1024:
  1014. Registers.Ecx |= BIOS_RES_1024x768;
  1015. break;
  1016. case 1152:
  1017. /*
  1018. * Only "Other" mode that the config program will
  1019. * install for production cards.
  1020. */
  1021. Registers.Ecx |= BIOS_RES_OEM;
  1022. break;
  1023. case 1280:
  1024. Registers.Ecx |= BIOS_RES_1280x1024;
  1025. break;
  1026. case 1600:
  1027. Registers.Ecx |= BIOS_RES_1600x1200;
  1028. break;
  1029. }
  1030. if (CrtTable->Refresh == DEFAULT_REFRESH)
  1031. {
  1032. RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
  1033. if (RetVal != NO_ERROR)
  1034. {
  1035. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed mode set for default refresh\n"));
  1036. return RetVal;
  1037. }
  1038. if (phwDeviceExtension->BiosPrefix != BIOS_PREFIX_VGA_ENAB)
  1039. {
  1040. VideoDebugPrint((DEBUG_DETAIL, "Have set hardware default refresh on VGA-disabled card\n"));
  1041. /*
  1042. * On VGA-disabled cards, the INT 10 call will leave the
  1043. * DAC mask set to 0x00 (in palette modes, treat all pixels
  1044. * as if they are colour 0, regardless of what colour they
  1045. * really are). We must set it to 0xFF (in palette modes,
  1046. * use all bits of the value written to each pixel) in order
  1047. * to get the screen to display properly. This has no effect
  1048. * on non-palette (16BPP and higher) modes.
  1049. */
  1050. OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
  1051. }
  1052. }
  1053. else
  1054. {
  1055. RetVal = SetModeFromTable_cx(CrtTable, Registers);
  1056. if (RetVal != NO_ERROR)
  1057. {
  1058. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed call to SetModeFromTable_cx()\n"));
  1059. return RetVal;
  1060. }
  1061. }
  1062. /*
  1063. * If the LFB is disabled, and we had to round up the pitch
  1064. * to 2048 (1152x864, 1280x1024, or 1600x1200), set the pitch
  1065. * registers manually, because there's no option in the
  1066. * INT 10 call to set them to anything other than 1024 or the
  1067. * screen width.
  1068. */
  1069. if (CrtTable->m_screen_pitch == 2048)
  1070. {
  1071. OUTPD(CRTC_OFF_PITCH, ((INPD(CRTC_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
  1072. OUTPD(SRC_OFF_PITCH, ((INPD(SRC_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
  1073. OUTPD(DST_OFF_PITCH, ((INPD(DST_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
  1074. }
  1075. /*
  1076. * On 800x600, we must round the pitch up to a multiple of 64 to avoid
  1077. * screen warping on some DACs. Set the pitch registers to correspond
  1078. * to this.
  1079. */
  1080. else if (CrtTable->m_screen_pitch == 832)
  1081. {
  1082. OUTPD(CRTC_OFF_PITCH, ((INPD(CRTC_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
  1083. OUTPD(SRC_OFF_PITCH, ((INPD(SRC_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
  1084. OUTPD(DST_OFF_PITCH, ((INPD(DST_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
  1085. }
  1086. /*
  1087. * Set up the hardware cursor with colour 0 black and colour 1 white.
  1088. * Do this here rather than in Initialize_cx() because the cursor
  1089. * colours don't "take" unless we are in accelerator mode.
  1090. *
  1091. * On cards with 68860 DACs, the CUR_CLR0/1 registers don't set
  1092. * the cursor colours. Instead, the colours must be set using the
  1093. * DAC_CNTL and DAC_REGS registers. The cursor colour settings
  1094. * are independent of pixel depth because the 68860 doesn't
  1095. * support 4BPP, which is the only depth that requires a different
  1096. * setting for the cursor colours.
  1097. *
  1098. * Cursor colour initialization is done unconditionally, rather than
  1099. * only on the first graphics mode set, because otherwise testing a
  1100. * different pixel depth (most commonly testing 1024x768 4BPP when
  1101. * 1024x768 16BPP configured) may corrupt the cursor colours.
  1102. */
  1103. if ((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
  1104. (QueryPtr->q_DAC_type == DAC_TVP3026) ||
  1105. (QueryPtr->q_DAC_type == DAC_IBM514))
  1106. {
  1107. OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC) | 1));
  1108. /*
  1109. * On TVP3026 DAC, skip the OVERSCAN colour register.
  1110. */
  1111. if (QueryPtr->q_DAC_type == DAC_TVP3026)
  1112. {
  1113. OUTP(DAC_REGS, 1);
  1114. CursorProgOffset = 1; /* DAC_DATA */
  1115. }
  1116. else if (QueryPtr->q_DAC_type == DAC_ATI_68860)
  1117. {
  1118. OUTP(DAC_REGS, 0);
  1119. CursorProgOffset = 1; /* DAC_DATA */
  1120. }
  1121. else /* if (QueryPtr->q_DAC_type == DAC_IBM514) */
  1122. {
  1123. OUTP_HBHW(DAC_REGS, 1); /* Auto-increment */
  1124. OUTP(DAC_REGS, 0x40);
  1125. OUTP_HBLW(DAC_REGS, 0);
  1126. CursorProgOffset = 2; /* DAC_MASK */
  1127. }
  1128. LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 red */
  1129. LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 green */
  1130. LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 blue */
  1131. LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 red */
  1132. LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 green */
  1133. LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 blue */
  1134. OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC)));
  1135. }
  1136. else /* if (DAC not one of ATI68860, TVP3026, or IBM514) */
  1137. {
  1138. OUTPD(CUR_CLR0, 0x00000000);
  1139. /*
  1140. * On most Mach 64 cards, we must use only the lower 4 bits
  1141. * when setting up the white part of the cursor. On the
  1142. * ?T, however, we must set all 8 bits for each of the colour
  1143. * components.
  1144. *
  1145. * Verify that the VT/GT still need this after the final ASIC
  1146. * becomes available.
  1147. */
  1148. if ((QueryPtr->q_pix_depth == 4) &&
  1149. (QueryPtr->q_DAC_type != DAC_INTERNAL_CT) &&
  1150. (QueryPtr->q_DAC_type != DAC_INTERNAL_GT) &&
  1151. (QueryPtr->q_DAC_type != DAC_INTERNAL_VT))
  1152. {
  1153. OUTPD(CUR_CLR1, 0x0F0F0F0F);
  1154. }
  1155. else
  1156. {
  1157. OUTPD(CUR_CLR1, 0xFFFFFFFF);
  1158. }
  1159. }
  1160. /*
  1161. * phwDeviceExtension->ReInitializing becomes TRUE in
  1162. * IOCTL_VIDEO_SET_COLOR_REGISTERS packet of ATIMPStartIO().
  1163. *
  1164. * If this is the first time we are going into graphics mode,
  1165. * Turn on the graphics engine. Otherwise, set the palette
  1166. * to the last set of colours that was selected while in
  1167. * accelerator mode.
  1168. */
  1169. if (phwDeviceExtension->ReInitializing)
  1170. {
  1171. SetPalette_cx(phwDeviceExtension->Clut,
  1172. phwDeviceExtension->FirstEntry,
  1173. phwDeviceExtension->NumEntries);
  1174. }
  1175. else
  1176. {
  1177. /*
  1178. * Turn on the graphics engine.
  1179. */
  1180. OUTPD(GEN_TEST_CNTL, (INPD(GEN_TEST_CNTL) | GEN_TEST_CNTL_GuiEna));
  1181. }
  1182. /*
  1183. * If we are using a 68860 DAC or ?T internal DAC in a non-palette
  1184. * mode, identity map the palette.
  1185. */
  1186. if (((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
  1187. (QueryPtr->q_DAC_type == DAC_INTERNAL_CT) ||
  1188. (QueryPtr->q_DAC_type == DAC_INTERNAL_GT) ||
  1189. (QueryPtr->q_DAC_type == DAC_INTERNAL_VT)) &&
  1190. (QueryPtr->q_pix_depth > 8))
  1191. IdentityMapPalette_cx();
  1192. /*
  1193. * Clear the screen regardless of whether or not this is the
  1194. * first time we are going into graphics mode. This is done
  1195. * because in 3.50 and later releases of Windows NT, the
  1196. * screen will be filled with garbage if we don't clear it.
  1197. *
  1198. * 24BPP is not a legal setting for DP_DST_PIX_WID@DP_PIX_WID.
  1199. * Instead, use 8BPP, but tell the engine that the screen is
  1200. * 3 times as wide as it actually is.
  1201. */
  1202. if (CrtTable->ColourDepthInfo == BIOS_DEPTH_24BPP)
  1203. {
  1204. WidthToClear = CrtTable->m_x_size * 3;
  1205. ScreenPitch = (CrtTable->m_screen_pitch * 3) / 8;
  1206. PixelDepth = BIOS_DEPTH_8BPP;
  1207. /*
  1208. * Horizontal scissors are only valid in the range
  1209. * -4096 to +4095. If the horizontal resolution
  1210. * is high enough to put the scissor outside this
  1211. * range, clamp the scissors to the maximum
  1212. * permitted value.
  1213. */
  1214. HorScissors = QueryPtr->q_desire_x * 3;
  1215. if (HorScissors > 4095)
  1216. HorScissors = 4095;
  1217. HorScissors <<= 16;
  1218. }
  1219. else
  1220. {
  1221. WidthToClear = CrtTable->m_x_size;
  1222. ScreenPitch = CrtTable->m_screen_pitch / 8;
  1223. PixelDepth = CrtTable->ColourDepthInfo;
  1224. HorScissors = (QueryPtr->q_desire_x) << 16;
  1225. }
  1226. /*
  1227. * On some DAC/memory combinations, some modes which require more
  1228. * than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
  1229. * 1600x1200 16BPP) will have screen tearing at the 2M boundary.
  1230. *
  1231. * As a workaround, the offset field of all 3 CRTC/SRC/DST_OFF_PITCH
  1232. * registers must be set to put the 2M boundary at the start
  1233. * of a scanline.
  1234. *
  1235. * Other DAC/memory combinations are unaffected, but since this
  1236. * fix is nearly harmless (only ill effect is to make DCI unusable
  1237. * in these modes), we can catch all future combinations which
  1238. * suffer from this problem by assuming that all DAC/memory
  1239. * combinations are affected.
  1240. */
  1241. if ((QueryPtr->q_pix_depth == 24) &&
  1242. (QueryPtr->q_desire_x == 1280))
  1243. {
  1244. ScreenOffset = 0x40;
  1245. }
  1246. else if ((QueryPtr->q_pix_depth == 24) &&
  1247. (QueryPtr->q_desire_x == 1152))
  1248. {
  1249. ScreenOffset = 0x160;
  1250. }
  1251. else if ((QueryPtr->q_pix_depth == 16) &&
  1252. (QueryPtr->q_desire_x == 1600))
  1253. {
  1254. ScreenOffset = 0x90;
  1255. }
  1256. else /* all other DAC/resolution/pixel depth combinations */
  1257. {
  1258. ScreenOffset = 0;
  1259. }
  1260. CheckFIFOSpace_cx(TWO_WORDS);
  1261. Scratch = INPD(CRTC_OFF_PITCH) & ~CRTC_OFF_PITCH_Offset;
  1262. Scratch |= ScreenOffset;
  1263. OUTPD(CRTC_OFF_PITCH, Scratch);
  1264. Scratch = INPD(SRC_OFF_PITCH) & ~SRC_OFF_PITCH_Offset;
  1265. Scratch |= ScreenOffset;
  1266. OUTPD(SRC_OFF_PITCH, Scratch);
  1267. /*
  1268. * The pixel widths for destination,
  1269. * source, and host must be the same.
  1270. */
  1271. PixelDepth |= ((PixelDepth << 8) | (PixelDepth << 16));
  1272. CheckFIFOSpace_cx(ELEVEN_WORDS);
  1273. OUTPD(DP_WRITE_MASK, 0xFFFFFFFF);
  1274. OUTPD(DST_OFF_PITCH, (ScreenPitch << 22) | ScreenOffset);
  1275. OUTPD(DST_CNTL, (DST_CNTL_XDir | DST_CNTL_YDir));
  1276. OUTPD(DP_PIX_WIDTH, PixelDepth);
  1277. OUTPD(DP_SRC, (DP_FRGD_SRC_FG | DP_BKGD_SRC_BG | DP_MONO_SRC_ONE));
  1278. OUTPD(DP_MIX, ((MIX_FN_PAINT << 16) | MIX_FN_PAINT));
  1279. OUTPD(DP_FRGD_CLR, 0x0);
  1280. OUTPD(SC_LEFT_RIGHT, HorScissors);
  1281. OUTPD(SC_TOP_BOTTOM, (CrtTable->m_y_size) << 16);
  1282. OUTPD(DST_Y_X, 0);
  1283. OUTPD(DST_HEIGHT_WIDTH, (WidthToClear << 16) | CrtTable->m_y_size);
  1284. if (WaitForIdle_cx() == FALSE)
  1285. {
  1286. VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed WaitForIdle_cx()\n"));
  1287. return ERROR_INSUFFICIENT_BUFFER;
  1288. }
  1289. return NO_ERROR;
  1290. } /* SetCurrentMode_cx() */
  1291. /***************************************************************************
  1292. *
  1293. * void SetPalette_cx(lpPalette, StartIndex, Count);
  1294. *
  1295. * PPALETTEENTRY lpPalette; Colour values to plug into palette
  1296. * USHORT StartIndex; First palette entry to set
  1297. * USHORT Count; Number of palette entries to set
  1298. *
  1299. * DESCRIPTION:
  1300. * Set the desired number of palette entries to the specified colours,
  1301. * starting at the specified index. Colour values are stored in
  1302. * doublewords, in the order (low byte to high byte) RGBx.
  1303. *
  1304. * GLOBALS CHANGED:
  1305. * none
  1306. *
  1307. * CALLED BY:
  1308. * SetCurrentMode_cx() and IOCTL_VIDEO_SET_COLOR_REGISTERS packet
  1309. * of ATIMPStartIO()
  1310. *
  1311. * AUTHOR:
  1312. * unknown
  1313. *
  1314. * CHANGE HISTORY:
  1315. *
  1316. * TEST HISTORY:
  1317. *
  1318. ***************************************************************************/
  1319. void SetPalette_cx(PULONG lpPalette, USHORT StartIndex, USHORT Count)
  1320. {
  1321. int i;
  1322. BYTE *pPal=(BYTE *)lpPalette;
  1323. struct query_structure *Query; /* Information about the graphics card */
  1324. Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
  1325. /*
  1326. * In the current rev of the 88800GX, the memory mapped access
  1327. * to the DAC_REGS register is broken but the I/O mapped access
  1328. * works properly. Force the use of the I/O mapped access.
  1329. */
  1330. phwDeviceExtension->aVideoAddressMM[DAC_REGS] = 0;
  1331. /*
  1332. * If a video capture card is hooked up to the feature connector,
  1333. * it will only "see" the palette being set if we use the VGA
  1334. * palette registers. This applies only in 4 and 8BPP, and is
  1335. * not necessary for when we identity map the palette (needed
  1336. * on certain DACs in 16BPP and above).
  1337. *
  1338. * In a multi-headed setup, only the card with the VGA enabled is
  1339. * able to be programmed using the VGA registers. All others must
  1340. * be programmed using the accelerator registers. Since this is
  1341. * the only card where we can hook up a video capture card to the
  1342. * feature connector, we don't lose "snooping" capability by
  1343. * programming VGA-disabled cards through the accelerator registers.
  1344. */
  1345. if ((Query->q_pix_depth <= 8) && (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB))
  1346. {
  1347. VideoDebugPrint((DEBUG_DETAIL, "Setting palette via VGA registers\n"));
  1348. /*
  1349. * DAC_W_INDEX is 8 bytes into second block of VGA registers.
  1350. * We do not have a separate OUTP()able register for this one.
  1351. */
  1352. LioOutp(VGA_END_BREAK_PORT, (BYTE)StartIndex, 8);
  1353. for (i=0; i<Count; i++) /* this is number of colours to update */
  1354. {
  1355. /*
  1356. * DAC_DATA is 9 bytes into second block of VGA registers.
  1357. * We do not have a separate OUTP()able register for this one.
  1358. */
  1359. LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* red */
  1360. LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* green */
  1361. LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* blue */
  1362. pPal++;
  1363. }
  1364. }
  1365. else
  1366. {
  1367. VideoDebugPrint((DEBUG_DETAIL, "Setting palette via accelerator registers\n"));
  1368. OUTP(DAC_REGS,(BYTE)StartIndex); /* load DAC_W_INDEX@DAC_REGS with StartIndex */
  1369. for (i=0; i<Count; i++) /* this is number of colours to update */
  1370. {
  1371. /*
  1372. * DAC_DATA@DAC_REGS is high byte of low word.
  1373. */
  1374. OUTP_HBLW(DAC_REGS, *pPal++); /* red */
  1375. OUTP_HBLW(DAC_REGS, *pPal++); /* green */
  1376. OUTP_HBLW(DAC_REGS, *pPal++); /* blue */
  1377. pPal++;
  1378. }
  1379. }
  1380. /*
  1381. * Victor Tango requires a few registers to be re-initialized after
  1382. * setting the palette.
  1383. */
  1384. if (Query->q_DAC_type == DAC_INTERNAL_VT)
  1385. {
  1386. OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
  1387. OUTP(DAC_REGS, 0xFF); /* DAC_W_INDEX */
  1388. }
  1389. return;
  1390. } /* SetPalette_cx() */
  1391. /***************************************************************************
  1392. *
  1393. * void IdentityMapPalette_cx(void);
  1394. *
  1395. * DESCRIPTION:
  1396. * Set the entire palette to a grey scale whose intensity at each
  1397. * index is equal to the index value.
  1398. *
  1399. * GLOBALS CHANGED:
  1400. * none
  1401. *
  1402. * CALLED BY:
  1403. * SetCurrentMode_cx()
  1404. *
  1405. * AUTHOR:
  1406. * unknown
  1407. *
  1408. * CHANGE HISTORY:
  1409. *
  1410. * TEST HISTORY:
  1411. *
  1412. ***************************************************************************/
  1413. void IdentityMapPalette_cx(void)
  1414. {
  1415. unsigned long Index;
  1416. struct query_structure *Query; /* Information about the graphics card */
  1417. Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
  1418. /*
  1419. * In the current rev of the 88800GX, the memory mapped access
  1420. * to the DAC_REGS register is broken but the I/O mapped access
  1421. * works properly. Force the use of the I/O mapped access.
  1422. */
  1423. phwDeviceExtension->aVideoAddressMM[DAC_REGS] = 0;
  1424. OUTP(DAC_REGS, 0); // Start at first palette entry.
  1425. for (Index=0; Index<256; Index++) // Fill the whole palette.
  1426. {
  1427. /*
  1428. * DAC_DATA@DAC_REGS is high byte of low word.
  1429. */
  1430. OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // red
  1431. OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // green
  1432. OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // blue
  1433. }
  1434. /*
  1435. * Victor Tango requires a few registers to be re-initialized after
  1436. * setting the palette.
  1437. */
  1438. if (Query->q_DAC_type == DAC_INTERNAL_VT)
  1439. {
  1440. OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
  1441. OUTP(DAC_REGS, 0xFF); /* DAC_W_INDEX */
  1442. }
  1443. return;
  1444. } /* IdentityMapPalette_cx() */
  1445. /**************************************************************************
  1446. *
  1447. * void ResetDevice_cx(void);
  1448. *
  1449. * DESCRIPTION:
  1450. * Switch back to VGA mode.
  1451. *
  1452. * GLOBALS CHANGED:
  1453. * none
  1454. *
  1455. * CALLED BY:
  1456. * IOCTL_VIDEO_RESET_DEVICE packet of ATIMPStartIO()
  1457. *
  1458. * AUTHOR:
  1459. * Robert Wolff
  1460. *
  1461. * CHANGE HISTORY:
  1462. *
  1463. * TEST HISTORY:
  1464. *
  1465. ***************************************************************************/
  1466. void ResetDevice_cx(void)
  1467. {
  1468. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  1469. ULONG Scratch;
  1470. VideoDebugPrint((DEBUG_NORMAL, "ResetDevice_cx() - entry\n"));
  1471. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1472. Registers.Eax = BIOS_SET_MODE;
  1473. Registers.Ecx = BIOS_MODE_VGA;
  1474. VideoPortInt10(phwDeviceExtension, &Registers);
  1475. VideoDebugPrint((DEBUG_DETAIL, "ResetDevice_cx() - VGA controls screen\n"));
  1476. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1477. Registers.Eax = 0x3;
  1478. VideoPortInt10(phwDeviceExtension, &Registers);
  1479. VideoDebugPrint((DEBUG_NORMAL, "ResetDevice_cx() - exit\n"));
  1480. return;
  1481. } /* ResetDevice_cx() */
  1482. /**************************************************************************
  1483. *
  1484. * DWORD GetPowerManagement_cx();
  1485. *
  1486. * DESCRIPTION:
  1487. * Determine our current DPMS state.
  1488. *
  1489. * RETURN VALUE:
  1490. * Current DPMS state (VIDEO_POWER_STATE enumeration)
  1491. *
  1492. * GLOBALS CHANGED:
  1493. * none
  1494. *
  1495. * CALLED BY:
  1496. * ATIMPGetPower()
  1497. *
  1498. * AUTHOR:
  1499. * Robert Wolff
  1500. *
  1501. * CHANGE HISTORY:
  1502. *
  1503. * TEST HISTORY:
  1504. *
  1505. ***************************************************************************/
  1506. DWORD GetPowerManagement_cx(PHW_DEVICE_EXTENSION phwDeviceExtension)
  1507. {
  1508. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  1509. ASSERT(phwDeviceExtension != NULL);
  1510. /*
  1511. * Invoke the BIOS call to get the desired DPMS state. The BIOS call
  1512. * enumeration of DPMS states is in the same order as that in
  1513. * VIDEO_POWER_STATE, but it is zero-based instead of one-based.
  1514. */
  1515. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1516. Registers.Eax = BIOS_GET_DPMS;
  1517. VideoPortInt10(phwDeviceExtension, &Registers);
  1518. return (Registers.Ecx + 1);
  1519. } /* GetPowerManagement_cx() */
  1520. /**************************************************************************
  1521. *
  1522. * VP_STATUS SetPowerManagement_cx(DpmsState);
  1523. *
  1524. * DWORD DpmsState; Desired DPMS state (VIDEO_POWER_STATE enumeration)
  1525. *
  1526. * DESCRIPTION:
  1527. * Switch into the desired DPMS state.
  1528. *
  1529. * RETURN VALUE:
  1530. * NO_ERROR if successful
  1531. * ERROR_INVALID_PARAMETER if invalid state requested.
  1532. *
  1533. * GLOBALS CHANGED:
  1534. * none
  1535. *
  1536. * CALLED BY:
  1537. * IOCTL_VIDEO_SET_POWER_MANAGEMENT packet of ATIMPStartIO()
  1538. *
  1539. * AUTHOR:
  1540. * Robert Wolff
  1541. *
  1542. * CHANGE HISTORY:
  1543. *
  1544. * TEST HISTORY:
  1545. *
  1546. ***************************************************************************/
  1547. VP_STATUS SetPowerManagement_cx(DWORD DpmsState)
  1548. {
  1549. VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
  1550. /*
  1551. * Only accept valid states.
  1552. */
  1553. if ((DpmsState < VideoPowerOn) || (DpmsState > VideoPowerOff))
  1554. {
  1555. VideoDebugPrint((DEBUG_ERROR, "SetPowerManagement_cx - invalid DPMS state selected\n"));
  1556. return ERROR_INVALID_PARAMETER;
  1557. }
  1558. /*
  1559. * Invoke the BIOS call to set the desired DPMS state. The BIOS call
  1560. * enumeration of DPMS states is in the same order as that in
  1561. * VIDEO_POWER_STATE, but it is zero-based instead of one-based.
  1562. */
  1563. VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1564. Registers.Eax = BIOS_SET_DPMS;
  1565. Registers.Ecx = DpmsState - 1;
  1566. VideoPortInt10(phwDeviceExtension, &Registers);
  1567. return NO_ERROR;
  1568. } /* SetPowerManagement_cx() */
  1569. /**************************************************************************
  1570. *
  1571. * static VP_STATUS SetModeFromTable_cx(ModeTable, Registers);
  1572. *
  1573. * struct st_mode_table *ModeTable; Mode table to set up screen from
  1574. * VIDEO_X86_BIOS_ARGUMENTS Registers; Registers for INT 10 call
  1575. *
  1576. * DESCRIPTION:
  1577. * Switch into the graphics mode specified by ModeTable.
  1578. *
  1579. * RETURN VALUE:
  1580. * NO_ERROR if successful
  1581. * error code if failed
  1582. *
  1583. * GLOBALS CHANGED:
  1584. * none
  1585. *
  1586. * CALLED BY:
  1587. * SetCurrentMode_cx()
  1588. *
  1589. * AUTHOR:
  1590. * Robert Wolff
  1591. *
  1592. * CHANGE HISTORY:
  1593. * 96 05 15 Now checks return values from INT 10 calls.
  1594. *
  1595. * TEST HISTORY:
  1596. *
  1597. ***************************************************************************/
  1598. static VP_STATUS SetModeFromTable_cx(struct st_mode_table *ModeTable, VIDEO_X86_BIOS_ARGUMENTS Registers)
  1599. {
  1600. #define TBL_SET_BUFFER_SIZE 100
  1601. PUCHAR MappedBuffer; /* Pointer to buffer used for BIOS query */
  1602. struct cx_bios_set_from_table *CxTable; /* Mode table in Mach 64 BIOS format */
  1603. ULONG Scratch; /* Temporary variable */
  1604. struct query_structure *QueryPtr; /* Query information for the card */
  1605. VIDEO_X86_BIOS_ARGUMENTS TempRegs; /* Used in setting 640x480 8BPP to enable LFB */
  1606. BOOL FlippedPrimrary = FALSE; /* TRUE if we switched to VGA aperture on primrary card */
  1607. UCHAR SavedScreen[TBL_SET_BUFFER_SIZE]; /* Used to restore contents of primrary screen */
  1608. VP_STATUS RetVal; /* Value returned by routines called */
  1609. /*
  1610. * Get a formatted pointer into the query section of HwDeviceExtension.
  1611. * The CardInfo[] field is an unformatted buffer.
  1612. */
  1613. QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
  1614. /*
  1615. * To set the video mode from a table, we need to write the mode table
  1616. * to a buffer in physical memory below 1M. The nature of this block
  1617. * falls into one of two cases:
  1618. *
  1619. * Primrary (VGA enabled) card:
  1620. * We have already switched into video mode 0x62 (VGA 640x480 8BPP)
  1621. * to set up registers that under some circumstances are not set up
  1622. * by the accelerator mode set, so we have access to a 64k block
  1623. * starting at 0xA0000 which is backed by physical (video) memory
  1624. * and which we can write to without corrupting code and/or data
  1625. * being used by other processes.
  1626. *
  1627. * Secondary (VGA disabled) card:
  1628. * There is a VGA enabled card in the machine, which falls into
  1629. * one of five sub-cases:
  1630. *
  1631. * 1. VGA is in colour text mode
  1632. * We can use the offscreen portion of the buffer, and it doesn't
  1633. * matter whether or not the card is a Mach 64.
  1634. *
  1635. * 2. VGA is in mono text mode
  1636. * We can use the offscreen portion of the buffer, and it doesn't
  1637. * matter whether or not the card is a Mach 64.
  1638. *
  1639. * 3. VGA is in graphics mode
  1640. * We can use the beginning of the graphics screen, and it doesn't
  1641. * matter whether or not the card is a Mach 64.
  1642. *
  1643. * 4. VGA-enabled card is a Mach 64 in accelerator mode
  1644. * We can temporarily flip the primrary card's aperture status
  1645. * from LFB to VGA aperture, and use the start of the VGA
  1646. * aperture.
  1647. *
  1648. * 5. VGA-enabled card is another brand of accelerator, in accelerator mode
  1649. * This case should never occur, since NT should only run one video
  1650. * driver with VgaCompatible set to zero. If it is the ATI driver,
  1651. * a non-ATI card should not be in accelerator mode. If it is the
  1652. * driver for the non-ATI card, we will never receive a request
  1653. * to change into an accelerator mode on our card.
  1654. *
  1655. * We don't need to claim the whole block, but we should claim a bit
  1656. * more than the size of the mode table so the BIOS won't try to access
  1657. * unclaimed memory.
  1658. */
  1659. if (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB)
  1660. {
  1661. VideoDebugPrint((DEBUG_NORMAL, "Setting mode on primrary card\n"));
  1662. MappedBuffer = MapFramebuffer(0xA0000, TBL_SET_BUFFER_SIZE);
  1663. if (MappedBuffer == 0)
  1664. {
  1665. VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed MapFramebuffer()\n"));
  1666. return ERROR_INSUFFICIENT_BUFFER;
  1667. }
  1668. /*
  1669. * Tell the BIOS to load the CRTC parameters from a table,
  1670. * rather than using the configured refresh rate for this
  1671. * resolution, and let it know where the table is.
  1672. */
  1673. Registers.Eax = BIOS_LOAD_SET;
  1674. Registers.Edx = 0xA000;
  1675. Registers.Ebx = 0x0000;
  1676. Registers.Ecx &= ~BIOS_RES_MASK; /* Mask out code for configured resolution */
  1677. Registers.Ecx |= BIOS_RES_BUFFER;
  1678. }
  1679. else
  1680. {
  1681. /*
  1682. * This is a VGA disabled card. First try sub-cases 1 through 3.
  1683. */
  1684. VideoDebugPrint((DEBUG_NORMAL, "Setting mode on secondary card\n"));
  1685. MappedBuffer = GetVgaBuffer(TBL_SET_BUFFER_SIZE, 0, &(Registers.Edx), SavedScreen);
  1686. /*
  1687. * If we were unable to map the buffer, assume we are dealing
  1688. * with sub-case 4. We can't distinguish between sub-cases
  1689. * 4 and 5, since the code to report an error if we issue an
  1690. * invalid BIOS call is in the ATI video BIOS, which won't
  1691. * be present in sub-case 5. Users in this sub-case are on
  1692. * their own.
  1693. *
  1694. * For sub-case 4 (VGA-enabled card is a Mach 64 in accelerator
  1695. * mode), temporarily flip from LFB mode to VGA aperture mode
  1696. * so we can use the VGA aperture without destroying the contents
  1697. * of the screen.
  1698. */
  1699. if (MappedBuffer == 0)
  1700. {
  1701. FlippedPrimrary = TRUE;
  1702. VideoDebugPrint((DEBUG_DETAIL, "Temporary setting primrary card to VGA aperture\n"));
  1703. VideoPortZeroMemory(&TempRegs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1704. TempRegs.Eax = BIOS_PREFIX_VGA_ENAB | BIOS_APERTURE_LB;
  1705. TempRegs.Ecx = BIOS_VGA_APERTURE;
  1706. RetVal = VideoPortInt10(phwDeviceExtension, &TempRegs);
  1707. if (RetVal != NO_ERROR)
  1708. {
  1709. VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed VGA-enabled flip to VGA aperture\n"));
  1710. return RetVal;
  1711. }
  1712. MappedBuffer = MapFramebuffer(0xA0000, TBL_SET_BUFFER_SIZE);
  1713. if (MappedBuffer == 0)
  1714. {
  1715. VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed to map buffer on VGA-enabled card\n"));
  1716. return ERROR_INSUFFICIENT_BUFFER;
  1717. }
  1718. Registers.Edx = 0xA000;
  1719. /*
  1720. * Save the contents of the buffer so that we can restore it
  1721. * after we finish the mode set.
  1722. */
  1723. for (Scratch = 0; Scratch < TBL_SET_BUFFER_SIZE; Scratch++)
  1724. SavedScreen[Scratch] = VideoPortReadRegisterUchar(&(MappedBuffer[Scratch]));
  1725. }
  1726. /*
  1727. * Tell the BIOS to load the CRTC parameters from a table,
  1728. * rather than using the configured refresh rate for this
  1729. * resolution, and let it know where the table is.
  1730. */
  1731. Registers.Eax = BIOS_LOAD_SET;
  1732. Registers.Ebx = 0x0000;
  1733. Registers.Ecx &= ~BIOS_RES_MASK; /* Mask out code for configured resolution */
  1734. Registers.Ecx |= BIOS_RES_BUFFER;
  1735. } /* end if (VGA disabled card) */
  1736. CxTable = (struct cx_bios_set_from_table *)MappedBuffer;
  1737. /*
  1738. * Copy the mode table into the Mach 64 format table. First handle
  1739. * the fields that only require shifting and masking.
  1740. */
  1741. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_mode_select), (WORD)((Registers.Ecx & BIOS_RES_MASK) | CX_BS_MODE_SELECT_ACC));
  1742. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_tot_disp), (WORD)((ModeTable->m_h_disp << 8) | ModeTable->m_h_total));
  1743. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_sync_strt_wid), (WORD)((ModeTable->m_h_sync_wid << 8) | ModeTable->m_h_sync_strt));
  1744. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_sync_wid), (WORD)(ModeTable->m_v_sync_wid | CX_BS_V_SYNC_WID_CLK));
  1745. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_overscan), ModeTable->m_h_overscan);
  1746. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_overscan), ModeTable->m_v_overscan);
  1747. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_overscan_8b), ModeTable->m_overscan_8b);
  1748. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_overscan_gr), ModeTable->m_overscan_gr);
  1749. /*
  1750. * Next take care of fields which must be translated from our
  1751. * "canned" mode tables.
  1752. *
  1753. * The cx_crtc_gen_cntl field has only 3 bits that we use: interlace,
  1754. * MUX mode (all 1280x1024 noninterlaced modes), and force use of
  1755. * all parameters from the table (this bit is used by all the
  1756. * "canned" tables).
  1757. */
  1758. if ((ModeTable->m_disp_cntl) & 0x10)
  1759. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_INTERLACED | CX_BS_FLAGS_ALL_PARMS);
  1760. else if ((ModeTable->m_x_size > 1024) && (ModeTable->ClockFreq >= 100000000L))
  1761. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_MUX | CX_BS_FLAGS_ALL_PARMS);
  1762. else
  1763. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_ALL_PARMS);
  1764. /*
  1765. * Vertical parameters other than sync width are in skip-2 in
  1766. * the "canned" tables, but need to be in linear form for the Mach 64.
  1767. */
  1768. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_total), (WORD)(((ModeTable->m_v_total >> 1) & 0x0FFFC) | (ModeTable->m_v_total & 0x03)));
  1769. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_disp), (WORD)(((ModeTable->m_v_disp >> 1) & 0x0FFFC) | (ModeTable->m_v_disp & 0x03)));
  1770. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_sync_strt), (WORD)(((ModeTable->m_v_sync_strt >> 1) & 0x0FFFC) | (ModeTable->m_v_sync_strt & 0x03)));
  1771. /*
  1772. * The cx_dot_clock field takes the pixel clock frequency in units
  1773. * of 10 kHz.
  1774. */
  1775. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_dot_clock), (WORD)(ModeTable->ClockFreq / 10000L));
  1776. /*
  1777. * Now set up fields which have constant values.
  1778. */
  1779. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_reserved_1), 0);
  1780. VideoPortWriteRegisterUshort(&(CxTable->cx_bs_reserved_2), 0);
  1781. /*
  1782. * Some Mach64 cards need to have an internal flag set up before
  1783. * they can switch into certain resolutions. Cards which have
  1784. * these resolutions configured using INSTALL.EXE don't need this
  1785. * flag set up, so we don't need to do it when switching to a
  1786. * hardware default mode. Since we don't know if the card needs
  1787. * this flag for the resolution we are using, set it for all
  1788. * "canned" mode tables.
  1789. *
  1790. * Unfortunately, this flag will disable automatic "kickdown"
  1791. * to a lower refresh rate for high pixel depths when "use
  1792. * hardware default refresh rate" is selected. To avoid this
  1793. * problem, save the contents of the scratchpad register, set
  1794. * the flag, then after we set the mode we want, restore the
  1795. * contents of the scratchpad register.
  1796. */
  1797. Scratch = INPD(SCRATCH_REG1);
  1798. OUTPD(SCRATCH_REG1, Scratch | 0x00000200);
  1799. RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
  1800. if (RetVal != NO_ERROR)
  1801. {
  1802. VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed mode set\n"));
  1803. return RetVal;
  1804. }
  1805. /*
  1806. * If we are dealing with a VGA-disabled card (typically in a
  1807. * multiheaded setup, but under rare circumstances someone may
  1808. * be using a VGA-disabled Mach 64 with a separate VGA card),
  1809. * we must clean up after ourselves. First of all, the DAC_MASK
  1810. * register will have been left at zero by the BIOS call, which
  1811. * inhibits display of palette modes. Next, we must restore the
  1812. * contents of the buffer we used to store the CRT parameter table.
  1813. *
  1814. * Finally, if we obtained the buffer by setting a VGA-enabled
  1815. * Mach 64 in accelerator mode to use the VGA aperture, we must
  1816. * restore it to its previous aperture status. Since this will
  1817. * only happen in a multiheaded setup, and we only support PCI
  1818. * cards in such a setup (i.e. all cards have LFB available),
  1819. * we can safely assume that the VGA-enabled card was originally
  1820. * configured for LFB mode.
  1821. */
  1822. if (phwDeviceExtension->BiosPrefix != BIOS_PREFIX_VGA_ENAB)
  1823. {
  1824. VideoDebugPrint((DEBUG_DETAIL, "Cleaning up after mode set on VGA-disabled card\n"));
  1825. OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
  1826. for (Scratch = 0; Scratch < TBL_SET_BUFFER_SIZE; Scratch++)
  1827. VideoPortWriteRegisterUchar(&(MappedBuffer[Scratch]), SavedScreen[Scratch]);
  1828. if (FlippedPrimrary == TRUE)
  1829. {
  1830. VideoDebugPrint((DEBUG_DETAIL, "Setting primrary card back to LFB mode\n"));
  1831. VideoPortZeroMemory(&TempRegs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1832. TempRegs.Eax = BIOS_PREFIX_VGA_ENAB | BIOS_APERTURE_LB;
  1833. TempRegs.Ecx = BIOS_LINEAR_APERTURE;
  1834. RetVal = VideoPortInt10(phwDeviceExtension, &TempRegs);
  1835. if (RetVal != NO_ERROR)
  1836. {
  1837. VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed VGA-enabled flip to linear aperture\n"));
  1838. return RetVal;
  1839. }
  1840. }
  1841. }
  1842. OUTPD(SCRATCH_REG1, Scratch);
  1843. VideoPortFreeDeviceBase(phwDeviceExtension, MappedBuffer);
  1844. return NO_ERROR;
  1845. } /* SetModeFromTable_cx() */
  1846. /**************************************************************************
  1847. *
  1848. * void RestoreMemSize_cx(void);
  1849. *
  1850. * DESCRIPTION:
  1851. * Restore the "memory size" register on the card when switching out
  1852. * of a mode which requires this register to be set to a specific value.
  1853. *
  1854. * GLOBALS CHANGED:
  1855. * none
  1856. *
  1857. * CALLED BY:
  1858. * SetCurrentMode_cx() and ATIMPResetHw()
  1859. *
  1860. * AUTHOR:
  1861. * Robert Wolff
  1862. *
  1863. * CHANGE HISTORY:
  1864. *
  1865. * TEST HISTORY:
  1866. *
  1867. ***************************************************************************/
  1868. void RestoreMemSize_cx(void)
  1869. {
  1870. struct query_structure *QueryPtr; /* Query information for the card */
  1871. ULONG Scratch; /* Temporary variable */
  1872. /*
  1873. * Get a formatted pointer into the query section of HwDeviceExtension.
  1874. */
  1875. QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
  1876. Scratch = INPD(MEM_CNTL) & ~MEM_CNTL_MemSizeMsk;
  1877. switch(QueryPtr->q_memory_size)
  1878. {
  1879. case VRAM_512k:
  1880. Scratch |= MEM_CNTL_MemSize512k;
  1881. break;
  1882. case VRAM_1mb:
  1883. Scratch |= MEM_CNTL_MemSize1Mb;
  1884. break;
  1885. case VRAM_2mb:
  1886. Scratch |= MEM_CNTL_MemSize2Mb;
  1887. break;
  1888. case VRAM_4mb:
  1889. Scratch |= MEM_CNTL_MemSize4Mb;
  1890. break;
  1891. case VRAM_6mb:
  1892. Scratch |= MEM_CNTL_MemSize6Mb;
  1893. break;
  1894. case VRAM_8mb:
  1895. Scratch |= MEM_CNTL_MemSize8Mb;
  1896. break;
  1897. default:
  1898. break;
  1899. }
  1900. OUTPD(MEM_CNTL, Scratch);
  1901. return;
  1902. } /* RestoreMemSize_cx() */
  1903. /**************************************************************************
  1904. *
  1905. * VP_STATUS ShareVideoMemory_cx(RequestPacket, QueryPtr);
  1906. *
  1907. * PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
  1908. * struct query_structure *QueryPtr; Query information for the card
  1909. *
  1910. * DESCRIPTION:
  1911. * Allow applications to do direct screen access through DCI.
  1912. *
  1913. * RETURN VALUE:
  1914. * NO_ERROR if successful
  1915. * error code if failed
  1916. *
  1917. * CALLED BY:
  1918. * IOCTL_VIDEO_SHARE_VIDEO_MEMORY packet of ATIMPStartIO()
  1919. *
  1920. * AUTHOR:
  1921. * Robert Wolff
  1922. *
  1923. * CHANGE HISTORY:
  1924. *
  1925. * TEST HISTORY:
  1926. *
  1927. ***************************************************************************/
  1928. VP_STATUS ShareVideoMemory_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
  1929. {
  1930. PVIDEO_SHARE_MEMORY InputPtr; /* Pointer to input structure */
  1931. PVIDEO_SHARE_MEMORY_INFORMATION OutputPtr; /* Pointer to output structure */
  1932. PHYSICAL_ADDRESS ShareAddress; /* Physical address of video memory */
  1933. PVOID VirtualAddress; /* Virtual address to map video memory at */
  1934. ULONG SharedViewSize; /* Size of block to share */
  1935. ULONG SpaceType; /* Sparse or dense space? */
  1936. VP_STATUS Status; /* Status to return */
  1937. /*
  1938. * On some DAC/memory combinations, some modes which require more
  1939. * than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
  1940. * 1600x1200 16BPP) will have screen tearing at the 2M boundary.
  1941. *
  1942. * As a workaround, the display driver must start the framebuffer
  1943. * at an offset which will put the 2M boundary at the start of a
  1944. * scanline.
  1945. *
  1946. * Other DAC/memory combinations are unaffected, but since this
  1947. * fix is nearly harmless (only ill effect is to make DCI unusable
  1948. * in these modes), we can catch all future combinations which
  1949. * suffer from this problem by assuming that all DAC/memory
  1950. * combinations are affected.
  1951. *
  1952. * Since this requires anyone making direct access to video memory
  1953. * to be aware of the workaround, we can't make the memory available
  1954. * through DCI.
  1955. */
  1956. if (((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1280)) ||
  1957. ((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1152)) ||
  1958. ((QueryPtr->q_pix_depth == 16) && (QueryPtr->q_desire_x == 1600)))
  1959. return ERROR_INVALID_FUNCTION;
  1960. InputPtr = RequestPacket->InputBuffer;
  1961. if ((InputPtr->ViewOffset > phwDeviceExtension->VideoRamSize) ||
  1962. ((InputPtr->ViewOffset + InputPtr->ViewSize) > phwDeviceExtension->VideoRamSize))
  1963. {
  1964. VideoDebugPrint((DEBUG_ERROR, "ShareVideoMemory_cx() - access beyond video memory\n"));
  1965. return ERROR_INVALID_PARAMETER;
  1966. }
  1967. RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  1968. /*
  1969. * Beware: the input buffer and the output buffer are the same buffer,
  1970. * and therefore data should not be copied from one to the other.
  1971. */
  1972. VirtualAddress = InputPtr->ProcessHandle;
  1973. SharedViewSize = InputPtr->ViewSize;
  1974. SpaceType = 0;
  1975. #if defined(_ALPHA_)
  1976. /*
  1977. * Use dense space mapping whenever we can, because that will
  1978. * allow us to support DCI and direct GDI access.
  1979. *
  1980. * Dense space is extremely slow with ISA cards on the newer Alphas,
  1981. * because any byte- or word-write requires a read/modify/write
  1982. * operation, and the ALpha can only ever do 64-bit reads when in
  1983. * dense mode. As a result, these operations would always require
  1984. * 4 reads and 2 writes on the ISA bus. Also, some older Alphas
  1985. * don't support dense space mapping.
  1986. *
  1987. * Any Alpha that supports PCI can support dense space mapping, and
  1988. * because the bus is wider and faster, the read/modify/write has
  1989. * less of an impact on performance.
  1990. */
  1991. if (QueryPtr->q_bus_type == BUS_PCI)
  1992. SpaceType = 4;
  1993. #endif
  1994. /*
  1995. * NOTE: we are ignoring ViewOffset
  1996. */
  1997. ShareAddress.QuadPart = phwDeviceExtension->PhysicalFrameAddress.QuadPart;
  1998. /*
  1999. * If the LFB is enabled, use ordinary mapping. If we have only
  2000. * the paged aperture, we must map to banked memory. Since the
  2001. * LFB is always aligned on a 4M boundary (8M boundary for 8M
  2002. * aperture), this check for the paged aperture will never falsely
  2003. * detect a LFB as paged.
  2004. */
  2005. if (phwDeviceExtension->PhysicalFrameAddress.LowPart == 0x0A0000)
  2006. {
  2007. /*
  2008. * On some versions of the DDK, VideoPortMapBankedMemory() is
  2009. * not available. If this is the case, force an error.
  2010. * This routine should be available in all versions of
  2011. * the DDK which support DCI, since it is used for DCI
  2012. * support on cards with banked apertures.
  2013. */
  2014. #if defined(IOCTL_VIDEO_SHARE_VIDEO_MEMORY)
  2015. Status = VideoPortMapBankedMemory(
  2016. phwDeviceExtension,
  2017. ShareAddress,
  2018. &SharedViewSize,
  2019. &SpaceType,
  2020. &VirtualAddress,
  2021. 0x10000, /* Only first 64k of 128k aperture available */
  2022. FALSE, /* No separate read/write banks */
  2023. BankMap_cx, /* Our bank-mapping routine */
  2024. (PVOID) phwDeviceExtension);
  2025. #else
  2026. Status = ERROR_INVALID_FUNCTION;
  2027. #endif
  2028. }
  2029. else /* LFB */
  2030. {
  2031. Status = VideoPortMapMemory(phwDeviceExtension,
  2032. ShareAddress,
  2033. &SharedViewSize,
  2034. &SpaceType,
  2035. &VirtualAddress);
  2036. }
  2037. OutputPtr = RequestPacket->OutputBuffer;
  2038. OutputPtr->SharedViewOffset = InputPtr->ViewOffset;
  2039. OutputPtr->VirtualAddress = VirtualAddress;
  2040. OutputPtr->SharedViewSize = SharedViewSize;
  2041. return Status;
  2042. } /* ShareVideoMemory_cx() */
  2043. /**************************************************************************
  2044. *
  2045. * void BankMap_cx(BankRead, BankWrite, Context);
  2046. *
  2047. * ULONG BankRead; Bank to read
  2048. * ULONG BankWrite; Bank to write
  2049. * PVOID Context; Pointer to hardware-specific information
  2050. *
  2051. * DESCRIPTION:
  2052. * Map the selected bank of video memory into the 64k VGA aperture.
  2053. * We don't support separate read and write banks, so we use BankWrite
  2054. * to set the read/write bank, and ignore BankRead.
  2055. *
  2056. * CALLED BY:
  2057. * This is an entry point, rather than being called
  2058. * by other miniport functions.
  2059. *
  2060. * NOTE:
  2061. * This function is called directly by the memory manager during page
  2062. * fault handling, and so cannot be made pageable.
  2063. *
  2064. * AUTHOR:
  2065. * Robert Wolff
  2066. *
  2067. * CHANGE HISTORY:
  2068. *
  2069. * TEST HISTORY:
  2070. *
  2071. ***************************************************************************/
  2072. void BankMap_cx(ULONG BankRead, ULONG BankWrite, PVOID Context)
  2073. {
  2074. OUTPD(MEM_VGA_WP_SEL, (BankWrite*2) | (BankWrite*2 + 1) << 16);
  2075. OUTPD(MEM_VGA_RP_SEL, (BankWrite*2) | (BankWrite*2 + 1) << 16);
  2076. return;
  2077. } /* BankMap_cx() */