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

1750 lines
56 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: enable.c
  3. *
  4. * This module contains the functions that enable and disable the
  5. * driver, the pdev, and the surface.
  6. *
  7. * Copyright (c) 1992-1995 Microsoft Corporation
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. BOOL bGetChipIDandRev(HANDLE hDriver, PPDEV ppdev);
  11. BYTE* gpjBase;
  12. BYTE* gpjPorts;
  13. BYTE* gpjMmu0;
  14. /******************************Public*Structure****************************\
  15. * GDIINFO ggdiDefault
  16. *
  17. * This contains the default GDIINFO fields that are passed back to GDI
  18. * during DrvEnablePDEV.
  19. *
  20. * NOTE: This structure defaults to values for an 8bpp palette device.
  21. * Some fields are overwritten for different colour depths.
  22. \**************************************************************************/
  23. GDIINFO ggdiDefault = {
  24. GDI_DRIVER_VERSION, // ulVersion
  25. DT_RASDISPLAY, // ulTechnology
  26. 0, // ulHorzSize (filled in later)
  27. 0, // ulVertSize (filled in later)
  28. 0, // ulHorzRes (filled in later)
  29. 0, // ulVertRes (filled in later)
  30. 0, // cBitsPixel (filled in later)
  31. 0, // cPlanes (filled in later)
  32. 20, // ulNumColors (palette managed)
  33. 0, // flRaster (DDI reserved field)
  34. 0, // ulLogPixelsX (filled in later)
  35. 0, // ulLogPixelsY (filled in later)
  36. TC_RA_ABLE /* | TC_SCROLLBLT */,
  37. // flTextCaps --
  38. // Setting TC_SCROLLBLT tells console to scroll
  39. // by repainting the entire window. Otherwise,
  40. // scrolls are done by calling the driver to
  41. // do screen to screen copies.
  42. 0, // ulDACRed (filled in later)
  43. 0, // ulDACGreen (filled in later)
  44. 0, // ulDACBlue (filled in later)
  45. 0x0024, // ulAspectX
  46. 0x0024, // ulAspectY
  47. 0x0033, // ulAspectXY (one-to-one aspect ratio)
  48. 1, // xStyleStep
  49. 1, // yStyleSte;
  50. 3, // denStyleStep -- Styles have a one-to-one aspect
  51. // ratio, and every 'dot' is 3 pixels long
  52. { 0, 0 }, // ptlPhysOffset
  53. { 0, 0 }, // szlPhysSize
  54. 256, // ulNumPalReg
  55. // These fields are for halftone initialization. The actual values are
  56. // a bit magic, but seem to work well on our display.
  57. { // ciDevice
  58. { 6700, 3300, 0 }, // Red
  59. { 2100, 7100, 0 }, // Green
  60. { 1400, 800, 0 }, // Blue
  61. { 1750, 3950, 0 }, // Cyan
  62. { 4050, 2050, 0 }, // Magenta
  63. { 4400, 5200, 0 }, // Yellow
  64. { 3127, 3290, 0 }, // AlignmentWhite
  65. 20000, // RedGamma
  66. 20000, // GreenGamma
  67. 20000, // BlueGamma
  68. 0, 0, 0, 0, 0, 0 // No dye correction for raster displays
  69. },
  70. 0, // ulDevicePelsDPI (for printers only)
  71. PRIMARY_ORDER_CBA, // ulPrimaryOrder
  72. HT_PATSIZE_4x4_M, // ulHTPatternSize
  73. HT_FORMAT_8BPP, // ulHTOutputFormat
  74. HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
  75. 0, // ulVRefresh
  76. 0, // ulBltAlignment
  77. 0, // ulPanningHorzRes
  78. 0, // ulPanningVertRes
  79. };
  80. /******************************Public*Structure****************************\
  81. * DEVINFO gdevinfoDefault
  82. *
  83. * This contains the default DEVINFO fields that are passed back to GDI
  84. * during DrvEnablePDEV.
  85. *
  86. * NOTE: This structure defaults to values for an 8bpp palette device.
  87. * Some fields are overwritten for different colour depths.
  88. \**************************************************************************/
  89. #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  90. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\
  91. VARIABLE_PITCH | FF_DONTCARE,L"System"}
  92. #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  93. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  94. VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"}
  95. #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,\
  96. CLIP_STROKE_PRECIS,PROOF_QUALITY,\
  97. FIXED_PITCH | FF_DONTCARE, L"Courier"}
  98. DEVINFO gdevinfoDefault = {
  99. (GCAPS_OPAQUERECT
  100. | GCAPS_DITHERONREALIZE
  101. | GCAPS_PALMANAGED
  102. | GCAPS_MONO_DITHER
  103. | GCAPS_COLOR_DITHER
  104. | GCAPS_DIRECTDRAW
  105. | GCAPS_ASYNCMOVE
  106. ),
  107. // NOTE: Only enable ASYNCMOVE if your code
  108. // and hardware can handle DrvMovePointer
  109. // calls at any time, even while another
  110. // thread is in the middle of a drawing
  111. // call such as DrvBitBlt.
  112. // flGraphicsFlags
  113. SYSTM_LOGFONT, // lfDefaultFont
  114. HELVE_LOGFONT, // lfAnsiVarFont
  115. COURI_LOGFONT, // lfAnsiFixFont
  116. 0, // cFonts
  117. BMF_8BPP, // iDitherFormat
  118. 8, // cxDither
  119. 8, // cyDither
  120. 0 // hpalDefault (filled in later)
  121. };
  122. /******************************Public*Structure****************************\
  123. * DFVFN gadrvfn[]
  124. *
  125. * Build the driver function table gadrvfn with function index/address
  126. * pairs. This table tells GDI which DDI calls we support, and their
  127. * location (GDI does an indirect call through this table to call us).
  128. *
  129. * Why haven't we implemented DrvSaveScreenBits? To save code.
  130. *
  131. * When the driver doesn't hook DrvSaveScreenBits, USER simulates on-
  132. * the-fly by creating a temporary device-format-bitmap, and explicitly
  133. * calling DrvCopyBits to save/restore the bits. Since we already hook
  134. * DrvCreateDeviceBitmap, we'll end up using off-screen memory to store
  135. * the bits anyway (which would have been the main reason for implementing
  136. * DrvSaveScreenBits). So we may as well save some working set.
  137. \**************************************************************************/
  138. DRVFN gadrvfn[] = {
  139. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  140. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  141. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  142. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  143. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  144. { INDEX_DrvAssertMode, (PFN) DrvAssertMode },
  145. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  146. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  147. { INDEX_DrvTextOut, (PFN) DrvTextOut },
  148. { INDEX_DrvGetModes, (PFN) DrvGetModes },
  149. { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
  150. { INDEX_DrvSetPalette, (PFN) DrvSetPalette },
  151. { INDEX_DrvDitherColor, (PFN) DrvDitherColor },
  152. #if !DRIVER_PUNT_ALL
  153. { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
  154. { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
  155. { INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
  156. { INDEX_DrvPaint, (PFN) DrvPaint },
  157. { INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
  158. { INDEX_DrvCreateDeviceBitmap, (PFN) DrvCreateDeviceBitmap },
  159. { INDEX_DrvDeleteDeviceBitmap, (PFN) DrvDeleteDeviceBitmap },
  160. { INDEX_DrvGetDirectDrawInfo, (PFN) DrvGetDirectDrawInfo },
  161. { INDEX_DrvEnableDirectDraw, (PFN) DrvEnableDirectDraw },
  162. { INDEX_DrvDisableDirectDraw, (PFN) DrvDisableDirectDraw },
  163. #endif
  164. };
  165. ULONG gcdrvfn = sizeof(gadrvfn) / sizeof(DRVFN);
  166. /******************************Public*Routine******************************\
  167. * BOOL DrvEnableDriver
  168. *
  169. * Enables the driver by retrieving the drivers function table and version.
  170. *
  171. \**************************************************************************/
  172. BOOL DrvEnableDriver(
  173. ULONG iEngineVersion,
  174. ULONG cj,
  175. DRVENABLEDATA* pded)
  176. {
  177. // Engine Version is passed down so future drivers can support previous
  178. // engine versions. A next generation driver can support both the old
  179. // and new engine conventions if told what version of engine it is
  180. // working with. For the first version the driver does nothing with it.
  181. DISPDBG((100, "DrvEnableDriver"));
  182. // Fill in as much as we can.
  183. if (cj >= sizeof(DRVENABLEDATA))
  184. pded->pdrvfn = gadrvfn;
  185. if (cj >= (sizeof(ULONG) * 2))
  186. pded->c = gcdrvfn;
  187. // DDI version this driver was targeted for is passed back to engine.
  188. // Future graphic's engine may break calls down to old driver format.
  189. if (cj >= sizeof(ULONG))
  190. pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
  191. return(TRUE);
  192. }
  193. /******************************Public*Routine******************************\
  194. * VOID DrvDisableDriver
  195. *
  196. * Tells the driver it is being disabled. Release any resources allocated in
  197. * DrvEnableDriver.
  198. *
  199. \**************************************************************************/
  200. VOID DrvDisableDriver(VOID)
  201. {
  202. return;
  203. }
  204. /******************************Public*Routine******************************\
  205. * DHPDEV DrvEnablePDEV
  206. *
  207. * Initializes a bunch of fields for GDI, based on the mode we've been asked
  208. * to do. This is the first thing called after DrvEnableDriver, when GDI
  209. * wants to get some information about us.
  210. *
  211. * (This function mostly returns back information; DrvEnableSurface is used
  212. * for initializing the hardware and driver components.)
  213. *
  214. \**************************************************************************/
  215. DHPDEV DrvEnablePDEV(
  216. DEVMODEW* pdm, // Contains data pertaining to requested mode
  217. PWSTR pwszLogAddr, // Logical address
  218. ULONG cPat, // Count of standard patterns
  219. HSURF* phsurfPatterns, // Buffer for standard patterns
  220. ULONG cjCaps, // Size of buffer for device caps 'pdevcaps'
  221. ULONG* pdevcaps, // Buffer for device caps, also known as 'gdiinfo'
  222. ULONG cjDevInfo, // Number of bytes in device info 'pdi'
  223. DEVINFO* pdi, // Device information
  224. HDEV hdev, // HDEV, used for callbacks
  225. PWSTR pwszDeviceName, // Device name
  226. HANDLE hDriver) // Kernel driver handle
  227. {
  228. PDEV* ppdev;
  229. // Future versions of NT had better supply 'devcaps' and 'devinfo'
  230. // structures that are the same size or larger than the current
  231. // structures:
  232. DISPDBG((100, "DrvEnablePDEV"));
  233. if ((cjCaps < sizeof(GDIINFO)) || (cjDevInfo < sizeof(DEVINFO)))
  234. {
  235. DISPDBG((0, "DrvEnablePDEV - Buffer size too small"));
  236. goto ReturnFailure0;
  237. }
  238. // Allocate a physical device structure. Note that we definitely
  239. // rely on the zero initialization:
  240. ppdev = (PDEV*) EngAllocMem(0, sizeof(PDEV), ALLOC_TAG);
  241. if (ppdev == NULL)
  242. {
  243. DISPDBG((0, "DrvEnablePDEV - Failed EngAllocMem"));
  244. goto ReturnFailure0;
  245. }
  246. memset(ppdev, 0, sizeof(PDEV));
  247. ppdev->hDriver = hDriver;
  248. if (!bGetChipIDandRev(hDriver, ppdev))
  249. {
  250. //
  251. // This puppy wasn't recognized as a W32
  252. //
  253. goto ReturnFailure1;
  254. }
  255. // Get the current screen mode information. Set up device caps and
  256. // devinfo:
  257. if (!bInitializeModeFields(ppdev, (GDIINFO*) pdevcaps, pdi, pdm))
  258. {
  259. goto ReturnFailure1;
  260. }
  261. // Initialize palette information.
  262. if (!bInitializePalette(ppdev, pdi))
  263. {
  264. DISPDBG((0, "DrvEnablePDEV - Failed bInitializePalette"));
  265. goto ReturnFailure1;
  266. }
  267. return((DHPDEV) ppdev);
  268. ReturnFailure1:
  269. DrvDisablePDEV((DHPDEV) ppdev);
  270. ReturnFailure0:
  271. DISPDBG((0, "Failed DrvEnablePDEV"));
  272. return(0);
  273. }
  274. /******************************Public*Routine******************************\
  275. * DrvDisablePDEV
  276. *
  277. * Release the resources allocated in DrvEnablePDEV. If a surface has been
  278. * enabled DrvDisableSurface will have already been called.
  279. *
  280. * Note that this function will be called when previewing modes in the
  281. * Display Applet, but not at system shutdown. If you need to reset the
  282. * hardware at shutdown, you can do it in the miniport by providing a
  283. * 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
  284. *
  285. * Note: In an error, we may call this before DrvEnablePDEV is done.
  286. *
  287. \**************************************************************************/
  288. VOID DrvDisablePDEV(
  289. DHPDEV dhpdev)
  290. {
  291. PDEV* ppdev;
  292. ppdev = (PDEV*) dhpdev;
  293. vUninitializePalette(ppdev);
  294. EngFreeMem(ppdev);
  295. }
  296. /******************************Public*Routine******************************\
  297. * VOID DrvCompletePDEV
  298. *
  299. * Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
  300. *
  301. \**************************************************************************/
  302. VOID DrvCompletePDEV(
  303. DHPDEV dhpdev,
  304. HDEV hdev)
  305. {
  306. ((PDEV*) dhpdev)->hdevEng = hdev;
  307. }
  308. /******************************Public*Routine******************************\
  309. * HSURF DrvEnableSurface
  310. *
  311. * Creates the drawing surface, initializes the hardware, and initializes
  312. * driver components. This function is called after DrvEnablePDEV, and
  313. * performs the final device initialization.
  314. *
  315. \**************************************************************************/
  316. HSURF DrvEnableSurface(
  317. DHPDEV dhpdev)
  318. {
  319. PDEV* ppdev;
  320. HSURF hsurf;
  321. SIZEL sizl;
  322. DSURF* pdsurf;
  323. VOID* pvTmpBuffer;
  324. ppdev = (PDEV*) dhpdev;
  325. /////////////////////////////////////////////////////////////////////
  326. // First, enable all the subcomponents.
  327. //
  328. // Note that the order in which these 'Enable' functions are called
  329. // may be significant in low off-screen memory conditions, because
  330. // the off-screen heap manager may fail some of the later
  331. // allocations...
  332. if (!bEnableHardware(ppdev))
  333. goto ReturnFailure;
  334. if (!bEnableBanking(ppdev))
  335. goto ReturnFailure;
  336. if (!bEnableOffscreenHeap(ppdev))
  337. goto ReturnFailure;
  338. if (!bEnablePointer(ppdev))
  339. goto ReturnFailure;
  340. if (!bEnableText(ppdev))
  341. goto ReturnFailure;
  342. if (!bEnableBrushCache(ppdev))
  343. goto ReturnFailure;
  344. if (!bEnablePalette(ppdev))
  345. goto ReturnFailure;
  346. if (!bEnableDirectDraw(ppdev))
  347. goto ReturnFailure;
  348. /////////////////////////////////////////////////////////////////////
  349. // Now create our private surface structure.
  350. //
  351. // Whenever we get a call to draw directly to the screen, we'll get
  352. // passed a pointer to a SURFOBJ whose 'dhpdev' field will point
  353. // to our PDEV structure, and whose 'dhsurf' field will point to the
  354. // following DSURF structure.
  355. //
  356. // Every device bitmap we create in DrvCreateDeviceBitmap will also
  357. // have its own unique DSURF structure allocated (but will share the
  358. // same PDEV). To make our code more polymorphic for handling drawing
  359. // to either the screen or an off-screen bitmap, we have the same
  360. // structure for both.
  361. pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(DSURF), ALLOC_TAG);
  362. if (pdsurf == NULL)
  363. {
  364. DISPDBG((0, "DrvEnableSurface - Failed pdsurf EngAllocMem"));
  365. goto ReturnFailure;
  366. }
  367. ppdev->pdsurfScreen = pdsurf; // Remember it for clean-up
  368. pdsurf->poh = ppdev->pohScreen; // The screen is a surface, too
  369. pdsurf->dt = DT_SCREEN; // Not to be confused with a DIB
  370. pdsurf->sizl.cx = ppdev->cxScreen;
  371. pdsurf->sizl.cy = ppdev->cyScreen;
  372. pdsurf->ppdev = ppdev;
  373. pdsurf->cBlt = 0;
  374. pdsurf->iUniq = 0;
  375. /////////////////////////////////////////////////////////////////////
  376. // Next, have GDI create the actual SURFOBJ.
  377. //
  378. // Our drawing surface is going to be 'device-managed', meaning that
  379. // GDI cannot draw on the framebuffer bits directly, and as such we
  380. // create the surface via EngCreateDeviceSurface. By doing this, we ensure
  381. // that GDI will only ever access the bitmaps bits via the Drv calls
  382. // that we've HOOKed.
  383. //
  384. // If we could map the entire framebuffer linearly into main memory
  385. // (i.e., we didn't have to go through a 64k aperture), it would be
  386. // beneficial to create the surface via EngCreateBitmap, giving GDI a
  387. // pointer to the framebuffer bits. When we pass a call on to GDI
  388. // where it can't directly read/write to the surface bits because the
  389. // surface is device managed, it has to create a temporary bitmap and
  390. // call our DrvCopyBits routine to get/set a copy of the affected bits.
  391. // For example, the OpenGL component prefers to be able to write on the
  392. // framebuffer bits directly.
  393. sizl.cx = ppdev->cxScreen;
  394. sizl.cy = ppdev->cyScreen;
  395. if (ppdev->bAutoBanking)
  396. {
  397. HSURF hsurfFrameBuf;
  398. // Engine-managed surface:
  399. hsurfFrameBuf = (HSURF) EngCreateBitmap(sizl,
  400. ppdev->lDelta,
  401. ppdev->iBitmapFormat,
  402. BMF_TOPDOWN,
  403. ppdev->pjScreen);
  404. if (hsurfFrameBuf == 0)
  405. {
  406. DISPDBG((0, "DrvEnableSurface - Failed EngCreateBitmap"));
  407. goto ReturnFailure;
  408. }
  409. if (!EngAssociateSurface(hsurfFrameBuf, ppdev->hdevEng, 0))
  410. {
  411. DISPDBG((0, "DrvEnableSurface - Failed EngAssociateSurface 1"));
  412. goto ReturnFailure;
  413. }
  414. ppdev->psoFrameBuffer = EngLockSurface(hsurfFrameBuf);
  415. if (ppdev->psoFrameBuffer == NULL)
  416. {
  417. DISPDBG((0, "DrvEnableSurface - Couldn't lock our surface"));
  418. goto ReturnFailure;
  419. }
  420. }
  421. hsurf = EngCreateDeviceSurface((DHSURF) pdsurf, sizl, ppdev->iBitmapFormat);
  422. if (hsurf == 0)
  423. {
  424. DISPDBG((0, "DrvEnableSurface - Failed EngCreateDeviceSurface"));
  425. goto ReturnFailure;
  426. }
  427. ppdev->hsurfScreen = hsurf; // Remember it for clean-up
  428. ppdev->bEnabled = TRUE; // We'll soon be in graphics mode
  429. /////////////////////////////////////////////////////////////////////
  430. // Now associate the surface and the PDEV.
  431. //
  432. // We have to associate the surface we just created with our physical
  433. // device so that GDI can get information related to the PDEV when
  434. // it's drawing to the surface (such as, for example, the length of
  435. // styles on the device when simulating styled lines).
  436. //
  437. if (!EngAssociateSurface(hsurf, ppdev->hdevEng, ppdev->flHooks))
  438. {
  439. DISPDBG((0, "DrvEnableSurface - Failed EngAssociateSurface 2"));
  440. goto ReturnFailure;
  441. }
  442. // Create our generic temporary buffer, which may be used by any
  443. // component.
  444. pvTmpBuffer = EngAllocMem(0, TMP_BUFFER_SIZE, ALLOC_TAG);
  445. if (pvTmpBuffer == NULL)
  446. {
  447. DISPDBG((0, "DrvEnableSurface - Failed VirtualAlloc"));
  448. goto ReturnFailure;
  449. }
  450. ppdev->pvTmpBuffer = pvTmpBuffer;
  451. DISPDBG((5, "Passed DrvEnableSurface"));
  452. return(hsurf);
  453. ReturnFailure:
  454. DrvDisableSurface((DHPDEV) ppdev);
  455. DISPDBG((0, "Failed DrvEnableSurface"));
  456. return(0);
  457. }
  458. /******************************Public*Routine******************************\
  459. * VOID DrvDisableSurface
  460. *
  461. * Free resources allocated by DrvEnableSurface. Release the surface.
  462. *
  463. * Note that this function will be called when previewing modes in the
  464. * Display Applet, but not at system shutdown. If you need to reset the
  465. * hardware at shutdown, you can do it in the miniport by providing a
  466. * 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
  467. *
  468. * Note: In an error case, we may call this before DrvEnableSurface is
  469. * completely done.
  470. *
  471. \**************************************************************************/
  472. VOID DrvDisableSurface(
  473. DHPDEV dhpdev)
  474. {
  475. PDEV* ppdev;
  476. ppdev = (PDEV*) dhpdev;
  477. // Note: In an error case, some of the following relies on the
  478. // fact that the PDEV is zero-initialized, so fields like
  479. // 'hsurfScreen' will be zero unless the surface has been
  480. // sucessfully initialized, and makes the assumption that
  481. // EngDeleteSurface can take '0' as a parameter.
  482. if (ppdev->bAutoBanking)
  483. {
  484. EngUnlockSurface(ppdev->psoFrameBuffer);
  485. }
  486. vDisableDirectDraw(ppdev);
  487. vDisablePalette(ppdev);
  488. vDisableBrushCache(ppdev);
  489. vDisableText(ppdev);
  490. vDisablePointer(ppdev);
  491. vDisableOffscreenHeap(ppdev);
  492. vDisableBanking(ppdev);
  493. vDisableHardware(ppdev);
  494. EngDeleteSurface(ppdev->hsurfScreen);
  495. if (ppdev->pvTmpBuffer)
  496. {
  497. EngFreeMem(ppdev->pvTmpBuffer);
  498. }
  499. if (ppdev->pdsurfScreen)
  500. {
  501. EngFreeMem(ppdev->pdsurfScreen);
  502. }
  503. }
  504. /******************************Public*Routine******************************\
  505. * VOID DrvAssertMode
  506. *
  507. * This asks the device to reset itself to the mode of the pdev passed in.
  508. *
  509. \**************************************************************************/
  510. BOOL DrvAssertMode(
  511. DHPDEV dhpdev,
  512. BOOL bEnable)
  513. {
  514. PDEV* ppdev;
  515. ppdev = (PDEV*) dhpdev;
  516. if (!bEnable)
  517. {
  518. //////////////////////////////////////////////////////////////
  519. // Disable - Switch to full-screen mode
  520. vAssertModeDirectDraw(ppdev, FALSE);
  521. vAssertModePalette(ppdev, FALSE);
  522. vAssertModeBrushCache(ppdev, FALSE);
  523. vAssertModeText(ppdev, FALSE);
  524. vAssertModePointer(ppdev, FALSE);
  525. if (bAssertModeOffscreenHeap(ppdev, FALSE))
  526. {
  527. vAssertModeBanking(ppdev, FALSE);
  528. if (bAssertModeHardware(ppdev, FALSE))
  529. {
  530. ppdev->bEnabled = FALSE;
  531. return(TRUE);
  532. }
  533. //////////////////////////////////////////////////////////
  534. // We failed to switch to full-screen. So undo everything:
  535. vAssertModeBanking(ppdev, TRUE);
  536. bAssertModeOffscreenHeap(ppdev, TRUE); // We don't need to check
  537. } // return code with TRUE
  538. vAssertModePointer(ppdev, TRUE);
  539. vAssertModeText(ppdev, TRUE);
  540. vAssertModeBrushCache(ppdev, TRUE);
  541. vAssertModePalette(ppdev, TRUE);
  542. }
  543. else
  544. {
  545. //////////////////////////////////////////////////////////////
  546. // Enable - Switch back to graphics mode
  547. // We have to enable every subcomponent in the reverse order
  548. // in which it was disabled:
  549. if (bAssertModeHardware(ppdev, TRUE))
  550. {
  551. vAssertModeBanking(ppdev, TRUE);
  552. bAssertModeOffscreenHeap(ppdev, TRUE); // We don't need to check
  553. // return code with TRUE
  554. vAssertModePointer(ppdev, TRUE);
  555. vAssertModeText(ppdev, TRUE);
  556. vAssertModeBrushCache(ppdev, TRUE);
  557. vAssertModePalette(ppdev, TRUE);
  558. ppdev->bEnabled = TRUE;
  559. return(TRUE);
  560. }
  561. }
  562. return(FALSE);
  563. }
  564. /******************************Public*Routine******************************\
  565. * ULONG DrvGetModes
  566. *
  567. * Returns the list of available modes for the device.
  568. *
  569. \**************************************************************************/
  570. ULONG DrvGetModes(
  571. HANDLE hDriver,
  572. ULONG cjSize,
  573. DEVMODEW* pdm)
  574. {
  575. DWORD cModes;
  576. DWORD cbOutputSize;
  577. PVIDEO_MODE_INFORMATION pVideoModeInformation;
  578. PVIDEO_MODE_INFORMATION pVideoTemp;
  579. DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  580. DWORD cbModeSize;
  581. if (!bGetChipIDandRev(hDriver, NULL))
  582. {
  583. //
  584. // This puppy wasn't recognized as a W32
  585. //
  586. return(0);
  587. }
  588. cModes = getAvailableModes(hDriver,
  589. (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
  590. &cbModeSize);
  591. if (cModes == 0)
  592. {
  593. DISPDBG((0, "DrvGetModes failed to get mode information"));
  594. return(0);
  595. }
  596. if (pdm == NULL)
  597. {
  598. cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  599. }
  600. else
  601. {
  602. //
  603. // Now copy the information for the supported modes back into the
  604. // output buffer
  605. //
  606. cbOutputSize = 0;
  607. pVideoTemp = pVideoModeInformation;
  608. do
  609. {
  610. if (pVideoTemp->Length != 0)
  611. {
  612. if (cOutputModes == 0)
  613. {
  614. break;
  615. }
  616. //
  617. // Zero the entire structure to start off with.
  618. //
  619. memset(pdm, 0, sizeof(DEVMODEW));
  620. //
  621. // Set the name of the device to the name of the DLL.
  622. //
  623. memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
  624. pdm->dmSpecVersion = DM_SPECVERSION;
  625. pdm->dmDriverVersion = DM_SPECVERSION;
  626. pdm->dmSize = sizeof(DEVMODEW);
  627. pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
  628. pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
  629. pVideoTemp->BitsPerPlane;
  630. pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
  631. pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
  632. pdm->dmDisplayFrequency = pVideoTemp->Frequency;
  633. pdm->dmDisplayFlags = 0;
  634. pdm->dmFields = DM_BITSPERPEL |
  635. DM_PELSWIDTH |
  636. DM_PELSHEIGHT |
  637. DM_DISPLAYFREQUENCY |
  638. DM_DISPLAYFLAGS ;
  639. //
  640. // Go to the next DEVMODE entry in the buffer.
  641. //
  642. cOutputModes--;
  643. pdm = (LPDEVMODEW) ( ((ULONG_PTR)pdm) + sizeof(DEVMODEW) +
  644. DRIVER_EXTRA_SIZE);
  645. cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
  646. }
  647. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  648. (((PUCHAR)pVideoTemp) + cbModeSize);
  649. } while (--cModes);
  650. }
  651. EngFreeMem(pVideoModeInformation);
  652. return(cbOutputSize);
  653. }
  654. /******************************Public*Routine******************************\
  655. * BOOL bAssertModeHardware
  656. *
  657. * Sets the appropriate hardware state for graphics mode or full-screen.
  658. *
  659. \**************************************************************************/
  660. BOOL bAssertModeHardware(
  661. PDEV* ppdev,
  662. BOOL bEnable)
  663. {
  664. DWORD ReturnedDataLength;
  665. ULONG ulReturn;
  666. VIDEO_MODE_INFORMATION VideoModeInfo;
  667. LONG cjEndOfFrameBuffer;
  668. LONG cjPointerOffset;
  669. LONG lDelta;
  670. ULONG ulMode;
  671. if (bEnable)
  672. {
  673. // Call the miniport via an IOCTL to set the graphics mode.
  674. ulMode = ppdev->ulMode;
  675. if (ppdev->bAutoBanking)
  676. {
  677. ulMode |= VIDEO_MODE_MAP_MEM_LINEAR;
  678. }
  679. if (EngDeviceIoControl(ppdev->hDriver,
  680. IOCTL_VIDEO_SET_CURRENT_MODE,
  681. &ulMode, // input buffer
  682. sizeof(DWORD),
  683. NULL,
  684. 0,
  685. &ReturnedDataLength))
  686. {
  687. DISPDBG((0, "bAssertModeHardware - Failed VIDEO_SET_CURRENT_MODE"));
  688. goto ReturnFalse;
  689. }
  690. if (EngDeviceIoControl(ppdev->hDriver,
  691. IOCTL_VIDEO_QUERY_CURRENT_MODE,
  692. NULL,
  693. 0,
  694. &VideoModeInfo,
  695. sizeof(VideoModeInfo),
  696. &ReturnedDataLength))
  697. {
  698. DISPDBG((0, "bAssertModeHardware - failed VIDEO_QUERY_CURRENT_MODE"));
  699. goto ReturnFalse;
  700. }
  701. #if DEBUG_HEAP
  702. VideoModeInfo.VideoMemoryBitmapWidth = VideoModeInfo.VisScreenWidth;
  703. VideoModeInfo.VideoMemoryBitmapHeight = VideoModeInfo.VisScreenHeight;
  704. #endif
  705. // The following variables are determined only after the initial
  706. // modeset:
  707. ppdev->lDelta = VideoModeInfo.ScreenStride;
  708. ppdev->flCaps = VideoModeInfo.AttributeFlags;
  709. ppdev->cxMemory = VideoModeInfo.VideoMemoryBitmapWidth;
  710. ppdev->cyMemory = VideoModeInfo.VideoMemoryBitmapHeight;
  711. DISPDBG((1,"ppdev->cxMemory = %d",ppdev->cxMemory));
  712. DISPDBG((1,"ppdev->cyMemory = %d",ppdev->cyMemory));
  713. #if DRIVER_PUNT_ALL
  714. //
  715. // Force SW cursor if PUNT_ALL
  716. //
  717. ppdev->flCaps |= CAPS_SW_POINTER;
  718. #endif
  719. if (ppdev->ulChipID != ET6000)
  720. {
  721. if ((ppdev->cBpp > 1) ||
  722. (ppdev->cxScreen > 1024))
  723. {
  724. ppdev->flCaps |= CAPS_SW_POINTER;
  725. }
  726. }
  727. if (ppdev->cxScreen < 512)
  728. {
  729. // The 320x240 and 320x200 modes can't use HW pointers
  730. ppdev->flCaps |= CAPS_SW_POINTER;
  731. }
  732. // If we're using the hardware pointer, reserve the last 1k of
  733. // the frame buffer to store the pointer shape:
  734. if (!(ppdev->flCaps & (CAPS_SW_POINTER)))
  735. {
  736. // Byte offset from start of frame buffer to end:
  737. cjEndOfFrameBuffer = ppdev->cyMemory * ppdev->lDelta;
  738. // We'll reserve the end of off-screen memory for the hardware
  739. // pointer shape.
  740. cjPointerOffset = (cjEndOfFrameBuffer - SPRITE_BUFFER_SIZE);
  741. // If we are using the ET6000 then we are going to round up to the
  742. // next 1K boundary. This is necessary because of the requirements
  743. // of the ET6000 sprite.
  744. if (ppdev->ulChipID == ET6000)
  745. {
  746. cjPointerOffset += 1023;
  747. cjPointerOffset &= 0xFFFFFC00;
  748. }
  749. // Figure out the coordinate where the pointer shape starts:
  750. lDelta = ppdev->lDelta;
  751. ppdev->cjPointerOffset = cjPointerOffset;
  752. ppdev->yPointerShape = (cjPointerOffset / lDelta);
  753. ppdev->xPointerShape = (cjPointerOffset % lDelta)
  754. / ppdev->cBpp;
  755. if (ppdev->yPointerShape >= ppdev->cyScreen)
  756. {
  757. // There's enough room for the pointer shape at the
  758. // bottom of off-screen memory; reserve its room by
  759. // lying about how much off-screen memory there is:
  760. ppdev->cyMemory = ppdev->yPointerShape;
  761. }
  762. else
  763. {
  764. // There's not enough room for the pointer shape in
  765. // off-screen memory; we'll have to simulate:
  766. ppdev->flCaps |= CAPS_SW_POINTER;
  767. }
  768. }
  769. {
  770. BYTE* pjBase = ppdev->pjBase;
  771. LONG lDeltaScreen;
  772. // Set the default state of the MMU Control Register so the ACL
  773. // can start. This must be done on pre W32p chips.
  774. if (ppdev->ulChipID != ET6000)
  775. {
  776. // Set a known state for all the MMU apertures, linear address,
  777. // non-accelerated.
  778. // Set MMU Aperture 2 so it will route its data to the ACL
  779. CP_MMU_CTRL(ppdev, pjBase, 0x70 | MMU_APERTURE_2_ACL_BIT);
  780. if (ppdev->ulChipID != W32P)
  781. {
  782. CP_STATE(ppdev, pjBase, 0x09);
  783. CP_X_POS_W32(ppdev, pjBase, 0);
  784. CP_Y_POS_W32(ppdev, pjBase, 0);
  785. }
  786. else
  787. {
  788. CP_X_POS_W32P(ppdev, pjBase, 0);
  789. CP_Y_POS_W32P(ppdev, pjBase, 0);
  790. }
  791. }
  792. // Set default values to the following registers.
  793. // These values should not change. If they are changed, it is the
  794. // responsiblity of the of the code that changed them to set them
  795. // back to the values they are set to here.
  796. CP_SRC_WRAP(ppdev, pjBase, NO_PATTERN_WRAP);
  797. if (ppdev->ulChipID == ET6000)
  798. {
  799. CP_ACL_CONFIG(ppdev, pjBase, 0x06);
  800. CP_ROUTING_CTRL(ppdev, pjBase, 0x33);
  801. }
  802. else
  803. {
  804. // Enable using wait-states to sync with the ACL QUEUE.
  805. CP_SYNC_ENABLE(ppdev, pjBase, 0x01);
  806. CP_ROUTING_CTRL(ppdev, pjBase, 0);
  807. }
  808. // Set the W32's source and destination offset registers.
  809. lDeltaScreen = ppdev->cxMemory;
  810. CP_SRC_Y_OFFSET(ppdev, pjBase, (lDeltaScreen - 1));
  811. CP_DST_Y_OFFSET(ppdev, pjBase, (lDeltaScreen - 1));
  812. // Set the default blit direction.
  813. CP_XY_DIR(ppdev, pjBase, 0);
  814. // The W32p overloads the Virtual Bus size register for use as the
  815. // ACL pixel depth register.
  816. // Set a default value for the ACL pixel depth to 1 byte.
  817. // This should be benign on the W32 and W32i.
  818. CP_BUS_SIZE(ppdev, pjBase, 0);
  819. // If this is a W32p then we must set ASEN in the OperationStateReg
  820. // the ACL can start.
  821. if ((ppdev->ulChipID == W32P) || (ppdev->ulChipID == ET6000))
  822. {
  823. CP_STATE(ppdev, pjBase, 0x10);
  824. }
  825. //
  826. // The following MUST be done for all pre-W32p chips. It must
  827. // also be done for W32p rev A chips because the register still
  828. // exists (though undocumented). The operation is harmless on
  829. // later chips, so just do it.
  830. //
  831. CP_RELOAD_CTRL(ppdev, pjBase, 0);
  832. //
  833. // An outside source has told us that certain ET6000 cards will
  834. // not correctly be reset during reboot if the ACL Transfer
  835. // Disable Register is not cleared. The BIOS will normally clear
  836. // this register during boot, but if the card gets hot, the
  837. // register isn't always cleared. We will clear it here just
  838. // to be sure.
  839. //
  840. if (ppdev->ulChipID == ET6000)
  841. {
  842. CP_XFER_DISABLE(ppdev, pjBase, 0);
  843. }
  844. }
  845. // Do some paramater checking on the values that the miniport
  846. // returned to us:
  847. ASSERTDD(ppdev->cxMemory >= ppdev->cxScreen, "Invalid cxMemory");
  848. ASSERTDD(ppdev->cyMemory >= ppdev->cyScreen, "Invalid cyMemory");
  849. }
  850. else
  851. {
  852. // Call the kernel driver to reset the device to a known state.
  853. // NTVDM will take things from there:
  854. if (EngDeviceIoControl(ppdev->hDriver,
  855. IOCTL_VIDEO_RESET_DEVICE,
  856. NULL,
  857. 0,
  858. NULL,
  859. 0,
  860. &ulReturn))
  861. {
  862. DISPDBG((0, "bAssertModeHardware - Failed reset IOCTL"));
  863. goto ReturnFalse;
  864. }
  865. }
  866. DISPDBG((5, "Passed bAssertModeHardware"));
  867. return(TRUE);
  868. ReturnFalse:
  869. DISPDBG((0, "Failed bAssertModeHardware"));
  870. return(FALSE);
  871. }
  872. /******************************Public*Routine******************************\
  873. * BOOL bEnableHardware
  874. *
  875. * Puts the hardware in the requested mode and initializes it.
  876. *
  877. * Note: Should be called before any access is done to the hardware from
  878. * the display driver.
  879. *
  880. \**************************************************************************/
  881. BOOL bEnableHardware(
  882. PDEV* ppdev)
  883. {
  884. VIDEO_MEMORY VideoMemory;
  885. VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
  886. DWORD ReturnedDataLength;
  887. DWORD uRet;
  888. VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange[3];
  889. ULONG ulMode;
  890. ulMode = ppdev->ulMode | VIDEO_MODE_MAP_MEM_LINEAR;
  891. if (EngDeviceIoControl(ppdev->hDriver,
  892. IOCTL_VIDEO_SET_CURRENT_MODE,
  893. &ulMode, // input buffer
  894. sizeof(DWORD),
  895. NULL,
  896. 0,
  897. &ReturnedDataLength))
  898. {
  899. ulMode &= ~VIDEO_MODE_MAP_MEM_LINEAR;
  900. if (EngDeviceIoControl(ppdev->hDriver,
  901. IOCTL_VIDEO_SET_CURRENT_MODE,
  902. &ulMode, // input buffer
  903. sizeof(DWORD),
  904. NULL,
  905. 0,
  906. &ReturnedDataLength))
  907. {
  908. DISPDBG((0, "bEnableHardware - Failed VIDEO_SET_CURRENT_MODE"));
  909. goto ReturnFalse;
  910. }
  911. }
  912. ppdev->bAutoBanking = (ulMode & VIDEO_MODE_MAP_MEM_LINEAR) ?
  913. TRUE : FALSE;
  914. if (EngDeviceIoControl(ppdev->hDriver,
  915. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  916. NULL,
  917. 0,
  918. (PVOID) &VideoAccessRange,
  919. sizeof (VideoAccessRange),
  920. &ReturnedDataLength) != NO_ERROR)
  921. {
  922. DISPDBG((0, "bEnableHardware - Error mapping access ranges."));
  923. goto ReturnFalse;
  924. }
  925. ppdev->pjMmu0 = gpjMmu0 = VideoAccessRange[0].VirtualAddress;
  926. ppdev->pjMmu1 = ppdev->pjMmu0 + 1 * 0x2000;
  927. ppdev->pjMmu2 = ppdev->pjMmu0 + 2 * 0x2000;
  928. ppdev->pjBase = gpjBase = VideoAccessRange[1].VirtualAddress;
  929. ppdev->pjPorts = gpjPorts = VideoAccessRange[2].VirtualAddress;
  930. // Get the linear memory address range.
  931. VideoMemory.RequestedVirtualAddress = NULL;
  932. uRet = EngDeviceIoControl(ppdev->hDriver,
  933. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  934. &VideoMemory, // input buffer
  935. sizeof(VIDEO_MEMORY),
  936. &VideoMemoryInfo, // output buffer
  937. sizeof(VideoMemoryInfo),
  938. &ReturnedDataLength);
  939. if (uRet != NO_ERROR)
  940. {
  941. DISPDBG((0, "bEnableHardware - Error mapping video buffer"));
  942. goto ReturnFalse;
  943. }
  944. DISPDBG((1, "FrameBufferBase(ie. pjScreen) %lx", VideoMemoryInfo.FrameBufferBase));
  945. DISPDBG((1, "FrameBufferLength %lx", VideoMemoryInfo.FrameBufferLength));
  946. // Record the Frame Buffer Linear Address.
  947. ppdev->pjScreen = (BYTE*) VideoMemoryInfo.FrameBufferBase;
  948. ppdev->cjBank = VideoMemoryInfo.FrameBufferLength;
  949. //ppdev->bAutoBanking = (VideoMemoryInfo.VideoRamLength ==
  950. // VideoMemoryInfo.FrameBufferLength)?
  951. // TRUE:FALSE;
  952. //
  953. // We've done the mapping for IO ports and memory space, so let's get
  954. // the pointer to the PCI config space. This is gotten from the CTRC
  955. // registers 21,22, & 23 on the ET6000.
  956. //
  957. if (ppdev->ulChipID == ET6000)
  958. {
  959. char a, b, c;
  960. OUTP(CRTC_INDEX, 0x23);
  961. a = INP(CRTC_DATA);
  962. OUTP(CRTC_INDEX, 0x22);
  963. b = INP(CRTC_DATA);
  964. OUTP(CRTC_INDEX, 0x21);
  965. c = INP(CRTC_DATA);
  966. ppdev->PCIConfigSpaceAddr =
  967. ((long) a << 24) | ((long) b << 16) | ((long) c << 8);
  968. }
  969. // Now we can set the mode and unlock the accelerator.
  970. if (!bAssertModeHardware(ppdev, TRUE))
  971. goto ReturnFalse;
  972. // Can do memory-mapped IO:
  973. if (ppdev->ulChipID == ET6000)
  974. {
  975. ppdev->pfnXfer1bpp = vET6000SlowXfer1bpp;
  976. }
  977. else
  978. {
  979. ppdev->pfnXfer1bpp = vSlowXfer1bpp;
  980. }
  981. ppdev->pfnFillPat = vPatternFillScr;
  982. ppdev->pfnCopyBlt = vScrToScr;
  983. ppdev->pfnFastPatRealize = vFastPatRealize;
  984. /////////////////////////////////////////////////////////////
  985. // Fill in pfns specific to color depth
  986. if (ppdev->cBpp == 3)
  987. {
  988. ppdev->pfnFillSolid = vSolidFillScr24;
  989. }
  990. else
  991. {
  992. ppdev->pfnFillSolid = vSolidFillScr;
  993. }
  994. /////////////////////////////////////////////////////////////
  995. // Fill in pfns specific to linear vs banked frame buffer
  996. if (ppdev->bAutoBanking)
  997. {
  998. ppdev->pfnGetBits = vGetBitsLinear;
  999. ppdev->pfnPutBits = vPutBitsLinear;
  1000. }
  1001. else
  1002. {
  1003. ppdev->pfnGetBits = vGetBits;
  1004. ppdev->pfnPutBits = vPutBits;
  1005. }
  1006. /////////////////////////////////////////////////////////////
  1007. // Fill in pfns specific to chip type
  1008. if (ppdev->ulChipID == W32P)
  1009. {
  1010. ppdev->pfnXferNative = vXferBlt8p;
  1011. }
  1012. else if (ppdev->ulChipID == ET6000)
  1013. {
  1014. ppdev->pfnXferNative = vXferET6000;
  1015. }
  1016. else
  1017. {
  1018. ppdev->pfnXferNative = vXferBlt8i;
  1019. }
  1020. #if DBG
  1021. {
  1022. DISPDBG((1, "cjBank: %lx, cxMemory: %li, cyMemory: %li, lDelta: %li, Flags: %lx",
  1023. ppdev->cjBank, ppdev->cxMemory, ppdev->cyMemory,
  1024. ppdev->lDelta, ppdev->flCaps));
  1025. if (ppdev->flCaps & CAPS_SW_POINTER)
  1026. {
  1027. DISPDBG((0, "Using software pointer"));
  1028. }
  1029. else
  1030. {
  1031. DISPDBG((0, "Using hardware pointer"));
  1032. }
  1033. DISPDBG((0, "%d bpp mode", ppdev->cBpp * 8));
  1034. if(ppdev->bAutoBanking)
  1035. {
  1036. DISPDBG((0, "Linear Mode"));
  1037. }
  1038. else
  1039. {
  1040. DISPDBG((0, "Banked Mode"));
  1041. }
  1042. }
  1043. #endif
  1044. DISPDBG((5, "Passed bEnableHardware"));
  1045. return(TRUE);
  1046. ReturnFalse:
  1047. DISPDBG((0, "Failed bEnableHardware"));
  1048. return(FALSE);
  1049. }
  1050. /******************************Public*Routine******************************\
  1051. * VOID vDisableHardware
  1052. *
  1053. * Undoes anything done in bEnableHardware.
  1054. *
  1055. * Note: In an error case, we may call this before bEnableHardware is
  1056. * completely done.
  1057. *
  1058. \**************************************************************************/
  1059. VOID vDisableHardware(
  1060. PDEV* ppdev)
  1061. {
  1062. DWORD ReturnedDataLength;
  1063. VIDEO_MEMORY VideoMemory[2];
  1064. VideoMemory[0].RequestedVirtualAddress = ppdev->pjScreen;
  1065. if (EngDeviceIoControl(ppdev->hDriver,
  1066. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  1067. VideoMemory,
  1068. sizeof(VIDEO_MEMORY),
  1069. NULL,
  1070. 0,
  1071. &ReturnedDataLength))
  1072. {
  1073. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_UNMAP_VIDEO"));
  1074. }
  1075. VideoMemory[0].RequestedVirtualAddress = ppdev->w32MmuInfo.pvMemoryBufferVirtualAddr;
  1076. if (EngDeviceIoControl(ppdev->hDriver,
  1077. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  1078. VideoMemory,
  1079. sizeof(VideoMemory),
  1080. NULL,
  1081. 0,
  1082. &ReturnedDataLength))
  1083. {
  1084. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_FREE_PUBLIC_ACCESS 1"));
  1085. }
  1086. VideoMemory[0].RequestedVirtualAddress = ppdev->w32MmuInfo.pvPortsVirtualAddr;
  1087. if (EngDeviceIoControl(ppdev->hDriver,
  1088. IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
  1089. VideoMemory,
  1090. sizeof(VideoMemory),
  1091. NULL,
  1092. 0,
  1093. &ReturnedDataLength))
  1094. {
  1095. DISPDBG((0, "vDisableHardware failed IOCTL_VIDEO_FREE_PUBLIC_ACCESS 2"));
  1096. }
  1097. }
  1098. /******************************Public*Routine******************************\
  1099. * BOOL bInitializeModeFields
  1100. *
  1101. * Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  1102. * devinfo based on the requested mode.
  1103. *
  1104. \**************************************************************************/
  1105. BOOL bInitializeModeFields(
  1106. PDEV* ppdev,
  1107. GDIINFO* pgdi,
  1108. DEVINFO* pdi,
  1109. DEVMODEW* pdm)
  1110. {
  1111. ULONG cModes;
  1112. PVIDEO_MODE_INFORMATION pVideoBuffer;
  1113. PVIDEO_MODE_INFORMATION pVideoModeSelected;
  1114. PVIDEO_MODE_INFORMATION pVideoTemp;
  1115. BOOL bSelectDefault;
  1116. VIDEO_MODE_INFORMATION VideoModeInformation;
  1117. ULONG cbModeSize;
  1118. // Call the miniport to get mode information
  1119. cModes = getAvailableModes(ppdev->hDriver, &pVideoBuffer, &cbModeSize);
  1120. if (cModes == 0)
  1121. goto ReturnFalse;
  1122. // Now see if the requested mode has a match in that table.
  1123. pVideoModeSelected = NULL;
  1124. pVideoTemp = pVideoBuffer;
  1125. if ((pdm->dmPelsWidth == 0) &&
  1126. (pdm->dmPelsHeight == 0) &&
  1127. (pdm->dmBitsPerPel == 0) &&
  1128. (pdm->dmDisplayFrequency == 0))
  1129. {
  1130. DISPDBG((1, "Default mode requested"));
  1131. bSelectDefault = TRUE;
  1132. }
  1133. else
  1134. {
  1135. DISPDBG((1, "Requested mode..."));
  1136. DISPDBG((1, " Screen width -- %li", pdm->dmPelsWidth));
  1137. DISPDBG((1, " Screen height -- %li", pdm->dmPelsHeight));
  1138. DISPDBG((1, " Bits per pel -- %li", pdm->dmBitsPerPel));
  1139. DISPDBG((1, " Frequency -- %li", pdm->dmDisplayFrequency));
  1140. bSelectDefault = FALSE;
  1141. }
  1142. while (cModes--)
  1143. {
  1144. if (pVideoTemp->Length != 0)
  1145. {
  1146. DISPDBG((2, " Checking against miniport mode:"));
  1147. DISPDBG((2, " Screen width -- %li", pVideoTemp->VisScreenWidth));
  1148. DISPDBG((2, " Screen height -- %li", pVideoTemp->VisScreenHeight));
  1149. DISPDBG((2, " Bits per pel -- %li", pVideoTemp->BitsPerPlane *
  1150. pVideoTemp->NumberOfPlanes));
  1151. DISPDBG((2, " Frequency -- %li", pVideoTemp->Frequency));
  1152. if (bSelectDefault ||
  1153. ((pVideoTemp->VisScreenWidth == pdm->dmPelsWidth) &&
  1154. (pVideoTemp->VisScreenHeight == pdm->dmPelsHeight) &&
  1155. (pVideoTemp->BitsPerPlane *
  1156. pVideoTemp->NumberOfPlanes == pdm->dmBitsPerPel) &&
  1157. (pVideoTemp->Frequency == pdm->dmDisplayFrequency)))
  1158. {
  1159. pVideoModeSelected = pVideoTemp;
  1160. DISPDBG((1, "...Found a mode match!"));
  1161. break;
  1162. }
  1163. }
  1164. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1165. (((PUCHAR)pVideoTemp) + cbModeSize);
  1166. }
  1167. // If no mode has been found, return an error
  1168. if (pVideoModeSelected == NULL)
  1169. {
  1170. DISPDBG((1, "...Couldn't find a mode match!"));
  1171. EngFreeMem(pVideoBuffer);
  1172. goto ReturnFalse;
  1173. }
  1174. // We have chosen the one we want. Save it in a stack buffer and
  1175. // get rid of allocated memory before we forget to free it.
  1176. VideoModeInformation = *pVideoModeSelected;
  1177. EngFreeMem(pVideoBuffer);
  1178. #if DEBUG_HEAP
  1179. VideoModeInformation.VisScreenWidth = 640;
  1180. VideoModeInformation.VisScreenHeight = 480;
  1181. #endif
  1182. // Set up screen information from the mini-port:
  1183. ppdev->ulMode = VideoModeInformation.ModeIndex;
  1184. ppdev->cxScreen = VideoModeInformation.VisScreenWidth;
  1185. ppdev->cyScreen = VideoModeInformation.VisScreenHeight;
  1186. DISPDBG((1, "ScreenStride: %lx", VideoModeInformation.ScreenStride));
  1187. ppdev->flHooks = (HOOK_BITBLT
  1188. | HOOK_TEXTOUT
  1189. | HOOK_COPYBITS
  1190. | HOOK_STROKEPATH
  1191. #if !DRIVER_PUNT_ALL
  1192. | HOOK_PAINT
  1193. | HOOK_STRETCHBLT
  1194. #endif
  1195. );
  1196. // Fill in the GDIINFO data structure with the default 8bpp values:
  1197. *pgdi = ggdiDefault;
  1198. // Now overwrite the defaults with the relevant information returned
  1199. // from the kernel driver:
  1200. pgdi->ulHorzSize = VideoModeInformation.XMillimeter;
  1201. pgdi->ulVertSize = VideoModeInformation.YMillimeter;
  1202. pgdi->ulHorzRes = VideoModeInformation.VisScreenWidth;
  1203. pgdi->ulVertRes = VideoModeInformation.VisScreenHeight;
  1204. pgdi->ulPanningHorzRes = VideoModeInformation.VisScreenWidth;
  1205. pgdi->ulPanningVertRes = VideoModeInformation.VisScreenHeight;
  1206. pgdi->cBitsPixel = VideoModeInformation.BitsPerPlane;
  1207. pgdi->cPlanes = VideoModeInformation.NumberOfPlanes;
  1208. pgdi->ulVRefresh = VideoModeInformation.Frequency;
  1209. pgdi->ulDACRed = VideoModeInformation.NumberRedBits;
  1210. pgdi->ulDACGreen = VideoModeInformation.NumberGreenBits;
  1211. pgdi->ulDACBlue = VideoModeInformation.NumberBlueBits;
  1212. pgdi->ulLogPixelsX = pdm->dmLogPixels;
  1213. pgdi->ulLogPixelsY = pdm->dmLogPixels;
  1214. // Fill in the devinfo structure with the default 8bpp values:
  1215. *pdi = gdevinfoDefault;
  1216. if (VideoModeInformation.BitsPerPlane == 8)
  1217. {
  1218. ppdev->w32PatternWrap = PATTERN_WRAP_8x8;
  1219. ppdev->cPelSize = 0;
  1220. ppdev->cBpp = 1;
  1221. ppdev->iBitmapFormat = BMF_8BPP;
  1222. ppdev->ulWhite = 0xff;
  1223. }
  1224. else if ((VideoModeInformation.BitsPerPlane == 16) ||
  1225. (VideoModeInformation.BitsPerPlane == 15))
  1226. {
  1227. ppdev->w32PatternWrap = PATTERN_WRAP_16x8;
  1228. ppdev->cPelSize = 1;
  1229. ppdev->cBpp = 2;
  1230. ppdev->iBitmapFormat = BMF_16BPP;
  1231. ppdev->ulWhite = 0xffff;
  1232. ppdev->flRed = VideoModeInformation.RedMask;
  1233. ppdev->flGreen = VideoModeInformation.GreenMask;
  1234. ppdev->flBlue = VideoModeInformation.BlueMask;
  1235. pgdi->ulNumColors = (ULONG) -1;
  1236. pgdi->ulNumPalReg = 0;
  1237. pgdi->ulHTOutputFormat = HT_FORMAT_16BPP;
  1238. pdi->iDitherFormat = BMF_16BPP;
  1239. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1240. }
  1241. else
  1242. {
  1243. ASSERTDD(VideoModeInformation.BitsPerPlane == 24,
  1244. "This driver supports only 8, 16 and 24bpp");
  1245. ppdev->w32PatternWrap = PATTERN_WRAP_32x8;
  1246. ppdev->cPelSize = 2;
  1247. ppdev->cBpp = 3;
  1248. ppdev->iBitmapFormat = BMF_24BPP;
  1249. ppdev->ulWhite = 0xffffff;
  1250. ppdev->flRed = VideoModeInformation.RedMask;
  1251. ppdev->flGreen = VideoModeInformation.GreenMask;
  1252. ppdev->flBlue = VideoModeInformation.BlueMask;
  1253. pgdi->ulNumColors = (ULONG) -1;
  1254. pgdi->ulNumPalReg = 0;
  1255. pgdi->ulHTOutputFormat = HT_FORMAT_24BPP;
  1256. pdi->iDitherFormat = BMF_24BPP;
  1257. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1258. }
  1259. DISPDBG((5, "Passed bInitializeModeFields"));
  1260. return(TRUE);
  1261. ReturnFalse:
  1262. DISPDBG((0, "Failed bInitializeModeFields"));
  1263. return(FALSE);
  1264. }
  1265. /******************************Public*Routine******************************\
  1266. * DWORD getAvailableModes
  1267. *
  1268. * Calls the miniport to get the list of modes supported by the kernel driver,
  1269. * and returns the list of modes supported by the diplay driver among those
  1270. *
  1271. * returns the number of entries in the videomode buffer.
  1272. * 0 means no modes are supported by the miniport or that an error occured.
  1273. *
  1274. * NOTE: the buffer must be freed up by the caller.
  1275. *
  1276. \**************************************************************************/
  1277. DWORD getAvailableModes(
  1278. HANDLE hDriver,
  1279. PVIDEO_MODE_INFORMATION* modeInformation,
  1280. DWORD* cbModeSize)
  1281. {
  1282. ULONG ulTemp;
  1283. VIDEO_NUM_MODES modes;
  1284. PVIDEO_MODE_INFORMATION pVideoTemp;
  1285. //
  1286. // Get the number of modes supported by the mini-port
  1287. //
  1288. if (EngDeviceIoControl(hDriver,
  1289. IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  1290. NULL,
  1291. 0,
  1292. &modes,
  1293. sizeof(VIDEO_NUM_MODES),
  1294. &ulTemp))
  1295. {
  1296. DISPDBG((0, "getAvailableModes - Failed VIDEO_QUERY_NUM_AVAIL_MODES"));
  1297. return(0);
  1298. }
  1299. *cbModeSize = modes.ModeInformationLength;
  1300. //
  1301. // Allocate the buffer for the mini-port to write the modes in.
  1302. //
  1303. *modeInformation = (PVIDEO_MODE_INFORMATION)
  1304. EngAllocMem(0, modes.NumModes *
  1305. modes.ModeInformationLength,
  1306. ALLOC_TAG);
  1307. if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL)
  1308. {
  1309. DISPDBG((0, "getAvailableModes - Failed EngAllocMem"));
  1310. return 0;
  1311. }
  1312. //
  1313. // Ask the mini-port to fill in the available modes.
  1314. //
  1315. if (EngDeviceIoControl(hDriver,
  1316. IOCTL_VIDEO_QUERY_AVAIL_MODES,
  1317. NULL,
  1318. 0,
  1319. *modeInformation,
  1320. modes.NumModes * modes.ModeInformationLength,
  1321. &ulTemp))
  1322. {
  1323. DISPDBG((0, "getAvailableModes - Failed VIDEO_QUERY_AVAIL_MODES"));
  1324. EngFreeMem(*modeInformation);
  1325. *modeInformation = (PVIDEO_MODE_INFORMATION) NULL;
  1326. return(0);
  1327. }
  1328. //
  1329. // Now see which of these modes are supported by the display driver.
  1330. // As an internal mechanism, set the length to 0 for the modes we
  1331. // DO NOT support.
  1332. //
  1333. ulTemp = modes.NumModes;
  1334. pVideoTemp = *modeInformation;
  1335. //
  1336. // Mode is rejected if it is not one plane, or not graphics, or is not
  1337. // one of 8, 15, 16 or 24 bits per pel.
  1338. //
  1339. while (ulTemp--)
  1340. {
  1341. if ((pVideoTemp->NumberOfPlanes != 1 ) ||
  1342. !(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
  1343. ((pVideoTemp->BitsPerPlane != 8)
  1344. && (pVideoTemp->BitsPerPlane != 15)
  1345. && (pVideoTemp->BitsPerPlane != 16)
  1346. && (pVideoTemp->BitsPerPlane != 24) // !!! will this work
  1347. ))
  1348. {
  1349. DISPDBG((2, "Rejecting miniport mode:"));
  1350. DISPDBG((2, " Screen width -- %li", pVideoTemp->VisScreenWidth));
  1351. DISPDBG((2, " Screen height -- %li", pVideoTemp->VisScreenHeight));
  1352. DISPDBG((2, " Bits per pel -- %li", pVideoTemp->BitsPerPlane *
  1353. pVideoTemp->NumberOfPlanes));
  1354. DISPDBG((2, " Frequency -- %li", pVideoTemp->Frequency));
  1355. pVideoTemp->Length = 0;
  1356. }
  1357. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  1358. (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
  1359. }
  1360. return(modes.NumModes);
  1361. }
  1362. /******************************Public*Routine******************************\
  1363. * BOOL bGetChipIDandRev
  1364. *
  1365. * Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  1366. * devinfo based on the requested mode.
  1367. *
  1368. * If bRetInfo is TRUE then pChipIDandRev is filled in.
  1369. *
  1370. * Returns TRUE if chip is one of the W32 family, FALSE otherwise
  1371. *
  1372. \**************************************************************************/
  1373. BOOL bGetChipIDandRev(HANDLE hDriver, PPDEV ppdev)
  1374. {
  1375. BYTE jChipID;
  1376. BOOL bRet = TRUE;
  1377. VIDEO_COPROCESSOR_INFORMATION VideoCoprocessorInfo;
  1378. DWORD ReturnedDataLength;
  1379. //
  1380. // Get information about the video card.
  1381. //
  1382. if (EngDeviceIoControl(hDriver,
  1383. IOCTL_VIDEO_GET_VIDEO_CARD_INFO,
  1384. NULL,
  1385. 0,
  1386. &VideoCoprocessorInfo,
  1387. sizeof(VIDEO_COPROCESSOR_INFORMATION),
  1388. &ReturnedDataLength))
  1389. {
  1390. RIP("bGetChipIDandRev - Couldn't get video card info");
  1391. bRet = FALSE;
  1392. goto ReturnStatus;
  1393. }
  1394. if (VideoCoprocessorInfo.ulChipID < W32)
  1395. {
  1396. bRet = FALSE;
  1397. goto ReturnStatus;
  1398. }
  1399. if (ppdev)
  1400. {
  1401. ppdev->ulChipID = VideoCoprocessorInfo.ulChipID;
  1402. ppdev->ulRevLevel = VideoCoprocessorInfo.ulRevLevel;
  1403. }
  1404. DISPDBG((1, "ulChipID = %d", VideoCoprocessorInfo.ulChipID));
  1405. DISPDBG((1, "ulRevLevel = %d", VideoCoprocessorInfo.ulRevLevel));
  1406. ReturnStatus:
  1407. return (bRet);
  1408. }