1 /*
2  * PROJECT:         ReactOS Framebuffer Display Driver
3  * LICENSE:         Microsoft NT4 DDK Sample Code License
4  * FILE:            win32ss/drivers/displays/vga_new/enable.c
5  * PURPOSE:         Main Driver Initialization and PDEV Enabling
6  * PROGRAMMERS:     Copyright (c) 1992-1995 Microsoft Corporation
7  *                  ReactOS Portable Systems Group
8  */
9 
10 #include "driver.h"
11 
12 // The driver function table with all function index/address pairs
13 
14 static DRVFN gadrvfn[] =
15 {
16     {   INDEX_DrvEnablePDEV,            (PFN) DrvEnablePDEV         },
17     {   INDEX_DrvCompletePDEV,          (PFN) DrvCompletePDEV       },
18     {   INDEX_DrvDisablePDEV,           (PFN) DrvDisablePDEV        },
19     {   INDEX_DrvEnableSurface,         (PFN) DrvEnableSurface      },
20     {   INDEX_DrvDisableSurface,        (PFN) DrvDisableSurface     },
21     {   INDEX_DrvAssertMode,            (PFN) DrvAssertMode         },
22 // eVb: 1.2 [VGARISC Change] - Disable hardware palette support
23     {   INDEX_DrvSetPalette,            (PFN) DrvSetPalette         },
24 // eVb: 1.2 [END]
25 // eVb: 1.1 [VGARISC Change] - Disable hardware pointer support
26 #if 0
27     {   INDEX_DrvMovePointer,           (PFN) DrvMovePointer        },
28     {   INDEX_DrvSetPointerShape,       (PFN) DrvSetPointerShape    },
29 #endif
30 // eVb: 1.1 [END]
31     {   INDEX_DrvGetModes,              (PFN) DrvGetModes           }
32 };
33 
34 // Define the functions you want to hook for 8/16/24/32 pel formats
35 
36 #define HOOKS_BMF8BPP 0
37 
38 #define HOOKS_BMF16BPP 0
39 
40 #define HOOKS_BMF24BPP 0
41 
42 #define HOOKS_BMF32BPP 0
43 
44 /******************************Public*Routine******************************\
45 * DrvEnableDriver
46 *
47 * Enables the driver by retrieving the drivers function table and version.
48 *
49 \**************************************************************************/
50 
51 BOOL APIENTRY DrvEnableDriver(
52 ULONG iEngineVersion,
53 ULONG cj,
54 PDRVENABLEDATA pded)
55 {
56 // Engine Version is passed down so future drivers can support previous
57 // engine versions.  A next generation driver can support both the old
58 // and new engine conventions if told what version of engine it is
59 // working with.  For the first version the driver does nothing with it.
60 // eVb: 1.1 [DDK Change] - Remove bogus statement
61     //iEngineVersion;
62 // eVb: 1.1 [END]
63 // Fill in as much as we can.
64 
65     if (cj >= sizeof(DRVENABLEDATA))
66         pded->pdrvfn = gadrvfn;
67 
68     if (cj >= (sizeof(ULONG) * 2))
69         pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
70 
71 // DDI version this driver was targeted for is passed back to engine.
72 // Future graphic's engine may break calls down to old driver format.
73 
74     if (cj >= sizeof(ULONG))
75 // eVb: 1.2 [DDK Change] - Use DDI_DRIVER_VERSION_NT4 instead of DDI_DRIVER_VERSION
76         pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
77 // eVb: 1.2 [END]
78 
79     return TRUE;
80 }
81 
82 /******************************Public*Routine******************************\
83 * DrvEnablePDEV
84 *
85 * DDI function, Enables the Physical Device.
86 *
87 * Return Value: device handle to pdev.
88 *
89 \**************************************************************************/
90 
91 DHPDEV APIENTRY DrvEnablePDEV(
92 DEVMODEW   *pDevmode,       // Pointer to DEVMODE
93 PWSTR       pwszLogAddress, // Logical address
94 ULONG       cPatterns,      // number of patterns
95 HSURF      *ahsurfPatterns, // return standard patterns
96 ULONG       cjGdiInfo,      // Length of memory pointed to by pGdiInfo
97 ULONG      *pGdiInfo,       // Pointer to GdiInfo structure
98 ULONG       cjDevInfo,      // Length of following PDEVINFO structure
99 DEVINFO    *pDevInfo,       // physical device information structure
100 HDEV        hdev,           // HDEV, used for callbacks
101 PWSTR       pwszDeviceName, // DeviceName - not used
102 HANDLE      hDriver)        // Handle to base driver
103 {
104     GDIINFO GdiInfo;
105     DEVINFO DevInfo;
106     PPDEV   ppdev = NULL;
107 
108     UNREFERENCED_PARAMETER(pwszLogAddress);
109     UNREFERENCED_PARAMETER(pwszDeviceName);
110 
111     // Allocate a physical device structure.
112 
113     ppdev = (PPDEV) EngAllocMem(0, sizeof(PDEV), ALLOC_TAG);
114 
115     if (ppdev == NULL)
116     {
117         RIP("DISP DrvEnablePDEV failed EngAllocMem\n");
118         return NULL;
119     }
120 
121     memset(ppdev, 0, sizeof(PDEV));
122 
123     // Save the screen handle in the PDEV.
124 
125     ppdev->hDriver = hDriver;
126 
127     // Get the current screen mode information.  Set up device caps and devinfo.
128 
129     if (!bInitPDEV(ppdev, pDevmode, &GdiInfo, &DevInfo))
130     {
131         DISPDBG((0,"DISP DrvEnablePDEV failed\n"));
132         goto error_free;
133     }
134 
135 // eVb: 1.2 [VGARISC Change] - Disable hardware pointer support
136 #if 0
137     // Initialize the cursor information.
138 
139     if (!bInitPointer(ppdev, &DevInfo))
140     {
141         // Not a fatal error...
142         DISPDBG((0, "DrvEnablePDEV failed bInitPointer\n"));
143     }
144 
145 #endif
146 // eVb: 1.2 [END]
147     // Initialize palette information.
148 
149     if (!bInitPaletteInfo(ppdev, &DevInfo))
150     {
151         RIP("DrvEnablePDEV failed bInitPalette\n");
152         goto error_free;
153     }
154 
155     // Copy the devinfo into the engine buffer.
156 
157     memcpy(pDevInfo, &DevInfo, min(sizeof(DEVINFO), cjDevInfo));
158 
159     // Set the pdevCaps with GdiInfo we have prepared to the list of caps for this
160     // pdev.
161 
162     memcpy(pGdiInfo, &GdiInfo, min(cjGdiInfo, sizeof(GDIINFO)));
163 
164     return (DHPDEV)ppdev;
165 
166     // Error case for failure.
167 error_free:
168     EngFreeMem(ppdev);
169     return NULL;
170 }
171 
172 /******************************Public*Routine******************************\
173 * DrvCompletePDEV
174 *
175 * Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
176 *
177 \**************************************************************************/
178 
179 VOID APIENTRY DrvCompletePDEV(
180 DHPDEV dhpdev,
181 HDEV  hdev)
182 {
183     ((PPDEV) dhpdev)->hdevEng = hdev;
184 }
185 
186 /******************************Public*Routine******************************\
187 * DrvDisablePDEV
188 *
189 * Release the resources allocated in DrvEnablePDEV.  If a surface has been
190 * enabled DrvDisableSurface will have already been called.
191 *
192 \**************************************************************************/
193 
194 VOID APIENTRY DrvDisablePDEV(
195 DHPDEV dhpdev)
196 {
197     vDisablePalette((PPDEV) dhpdev);
198     EngFreeMem(dhpdev);
199 }
200 
201 /******************************Public*Routine******************************\
202 * DrvEnableSurface
203 *
204 * Enable the surface for the device.  Hook the calls this driver supports.
205 *
206 * Return: Handle to the surface if successful, 0 for failure.
207 *
208 \**************************************************************************/
209 
210 HSURF APIENTRY DrvEnableSurface(
211 DHPDEV dhpdev)
212 {
213     PPDEV ppdev;
214     HSURF hsurf;
215     SIZEL sizl;
216     ULONG ulBitmapType;
217 #if 0
218     FLONG flHooks;
219 #endif
220     HSURF hSurfBitmap;
221 
222     // Create engine bitmap around frame buffer.
223 
224     ppdev = (PPDEV) dhpdev;
225 
226     if (!bInitSURF(ppdev, TRUE))
227     {
228         RIP("DISP DrvEnableSurface failed bInitSURF\n");
229         return NULL;
230     }
231 
232     sizl.cx = ppdev->cxScreen;
233     sizl.cy = ppdev->cyScreen;
234 
235 // eVb: 1.3 [VGARISC Change] - Disable dynamic palette and > 4BPP support
236 #if 0
237     if (ppdev->ulBitCount == 8)
238     {
239         if (!bInit256ColorPalette(ppdev)) {
240             RIP("DISP DrvEnableSurface failed to init the 8bpp palette\n");
241             return NULL;
242         }
243         ulBitmapType = BMF_8BPP;
244         flHooks = HOOKS_BMF8BPP;
245     }
246     else if (ppdev->ulBitCount == 16)
247     {
248         ulBitmapType = BMF_16BPP;
249         flHooks = HOOKS_BMF16BPP;
250     }
251     else if (ppdev->ulBitCount == 24)
252     {
253         ulBitmapType = BMF_24BPP;
254         flHooks = HOOKS_BMF24BPP;
255     }
256     else
257     {
258         ulBitmapType = BMF_32BPP;
259         flHooks = HOOKS_BMF32BPP;
260     }
261 // eVb: 1.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
262     ppdev->flHooks = flHooks;
263 // eVb: 1.3 [END]
264 #else
265     ulBitmapType = BMF_4BPP;
266 #endif
267 // eVb: 1.3 [END]
268 // eVb: 1.4 [DDK Change] - Use EngCreateDeviceSurface instead of EngCreateBitmap
269     hsurf = (HSURF)EngCreateDeviceSurface((DHSURF)ppdev,
270                                            sizl,
271                                            ulBitmapType);
272 
273     if (hsurf == NULL)
274     {
275         RIP("DISP DrvEnableSurface failed EngCreateDeviceSurface\n");
276         return NULL;
277     }
278 // eVb: 1.4 [END]
279 
280 // eVb: 1.5 [DDK Change] - Use EngModifySurface instead of EngAssociateSurface
281     if ( !EngModifySurface(hsurf,
282                            ppdev->hdevEng,
283                            ppdev->flHooks | HOOK_SYNCHRONIZE,
284                            MS_NOTSYSTEMMEMORY,
285                            (DHSURF)ppdev,
286                            ppdev->pjScreen,
287                            ppdev->lDeltaScreen,
288                            NULL))
289     {
290         RIP("DISP DrvEnableSurface failed EngModifySurface\n");
291         return NULL;
292     }
293 // eVb: 1.5 [END]
294     ppdev->hsurfEng = hsurf;
295 // eVb: 1.4 [VGARISC Change] - Allocate 4BPP DIB that will store GDI drawing
296     hSurfBitmap = (HSURF)EngCreateBitmap(sizl, 0, ulBitmapType, 0, NULL);
297     if (hSurfBitmap == NULL)
298     {
299         RIP("DISP DrvEnableSurface failed EngCreateBitmap\n");
300         return NULL;
301     }
302 
303     if ( !EngModifySurface(hSurfBitmap,
304                            ppdev->hdevEng,
305                            ppdev->flHooks | HOOK_SYNCHRONIZE,
306                            MS_NOTSYSTEMMEMORY,
307                            (DHSURF)ppdev,
308                            ppdev->pjScreen,
309                            ppdev->lDeltaScreen,
310                            NULL))
311     {
312         RIP("DISP DrvEnableSurface failed second EngModifySurface\n");
313         return NULL;
314     }
315 
316     ppdev->pso = EngLockSurface(hSurfBitmap);
317     if (ppdev->pso == NULL)
318     {
319         RIP("DISP DrvEnableSurface failed EngLockSurface\n");
320         return NULL;
321     }
322 // eVb: 1.4 [END]
323     return hsurf;
324 }
325 
326 /******************************Public*Routine******************************\
327 * DrvDisableSurface
328 *
329 * Free resources allocated by DrvEnableSurface.  Release the surface.
330 *
331 \**************************************************************************/
332 
333 VOID APIENTRY DrvDisableSurface(
334 DHPDEV dhpdev)
335 {
336     EngDeleteSurface(((PPDEV) dhpdev)->hsurfEng);
337     vDisableSURF((PPDEV) dhpdev);
338     ((PPDEV) dhpdev)->hsurfEng = NULL;
339 }
340 
341 /******************************Public*Routine******************************\
342 * DrvAssertMode
343 *
344 * This asks the device to reset itself to the mode of the pdev passed in.
345 *
346 \**************************************************************************/
347 
348 BOOL APIENTRY DrvAssertMode(
349 DHPDEV dhpdev,
350 BOOL bEnable)
351 {
352     PPDEV   ppdev = (PPDEV) dhpdev;
353     ULONG   ulReturn;
354     PBYTE   pjScreen;
355 
356     if (bEnable)
357     {
358         //
359         // The screen must be reenabled, reinitialize the device to clean state.
360         //
361 // eVb: 1.6 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
362         pjScreen = ppdev->pjScreen;
363 
364         if (!bInitSURF(ppdev, FALSE))
365         {
366             DISPDBG((0, "DISP DrvAssertMode failed bInitSURF\n"));
367             return (FALSE);
368         }
369 
370         if (pjScreen != ppdev->pjScreen) {
371 
372             if ( !EngModifySurface(ppdev->hsurfEng,
373                                    ppdev->hdevEng,
374                                    ppdev->flHooks | HOOK_SYNCHRONIZE,
375                                    MS_NOTSYSTEMMEMORY,
376                                    (DHSURF)ppdev,
377                                    ppdev->pjScreen,
378                                    ppdev->lDeltaScreen,
379                                    NULL))
380             {
381                 DISPDBG((0, "DISP DrvAssertMode failed EngModifySurface\n"));
382                 return (FALSE);
383             }
384         }
385 // eVb: 1.6 [END]
386         return (TRUE);
387     }
388     else
389     {
390         //
391         // We must give up the display.
392         // Call the kernel driver to reset the device to a known state.
393         //
394 
395         if (EngDeviceIoControl(ppdev->hDriver,
396                                IOCTL_VIDEO_RESET_DEVICE,
397                                NULL,
398                                0,
399                                NULL,
400                                0,
401                                &ulReturn))
402         {
403             RIP("DISP DrvAssertMode failed IOCTL");
404             return FALSE;
405         }
406         else
407         {
408             return TRUE;
409         }
410     }
411 }
412 
413 /******************************Public*Routine******************************\
414 * DrvGetModes
415 *
416 * Returns the list of available modes for the device.
417 *
418 \**************************************************************************/
419 
420 ULONG APIENTRY DrvGetModes(
421 HANDLE hDriver,
422 ULONG cjSize,
423 DEVMODEW *pdm)
424 
425 {
426 
427     DWORD cModes;
428     DWORD cbOutputSize;
429     PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
430     DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
431     DWORD cbModeSize;
432 
433     DISPDBG((3, "DrvGetModes\n"));
434 
435     cModes = getAvailableModes(hDriver,
436                                (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
437                                &cbModeSize);
438 
439     if (cModes == 0)
440     {
441         DISPDBG((0, "DrvGetModes failed to get mode information"));
442         return 0;
443     }
444 
445     if (pdm == NULL)
446     {
447         cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
448     }
449     else
450     {
451         //
452         // Now copy the information for the supported modes back into the output
453         // buffer
454         //
455 
456         cbOutputSize = 0;
457 
458         pVideoTemp = pVideoModeInformation;
459 
460         do
461         {
462             if (pVideoTemp->Length != 0)
463             {
464                 if (cOutputModes == 0)
465                 {
466                     break;
467                 }
468 
469                 //
470                 // Zero the entire structure to start off with.
471                 //
472 
473                 memset(pdm, 0, sizeof(DEVMODEW));
474 
475                 //
476                 // Set the name of the device to the name of the DLL.
477                 //
478 
479                 memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
480 
481                 pdm->dmSpecVersion      = DM_SPECVERSION;
482                 pdm->dmDriverVersion    = DM_SPECVERSION;
483                 pdm->dmSize             = sizeof(DEVMODEW);
484                 pdm->dmDriverExtra      = DRIVER_EXTRA_SIZE;
485 
486                 pdm->dmBitsPerPel       = pVideoTemp->NumberOfPlanes *
487                                           pVideoTemp->BitsPerPlane;
488                 pdm->dmPelsWidth        = pVideoTemp->VisScreenWidth;
489                 pdm->dmPelsHeight       = pVideoTemp->VisScreenHeight;
490                 pdm->dmDisplayFrequency = pVideoTemp->Frequency;
491                 pdm->dmDisplayFlags     = 0;
492 
493                 pdm->dmFields           = DM_BITSPERPEL       |
494                                           DM_PELSWIDTH        |
495                                           DM_PELSHEIGHT       |
496                                           DM_DISPLAYFREQUENCY |
497                                           DM_DISPLAYFLAGS     ;
498 
499                 //
500                 // Go to the next DEVMODE entry in the buffer.
501                 //
502 
503                 cOutputModes--;
504 
505                 pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
506                                                    DRIVER_EXTRA_SIZE);
507 
508                 cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
509 
510             }
511 
512             pVideoTemp = (PVIDEO_MODE_INFORMATION)
513                 (((PUCHAR)pVideoTemp) + cbModeSize);
514 
515         } while (--cModes);
516     }
517 
518     EngFreeMem(pVideoModeInformation);
519 
520     return cbOutputSize;
521 
522 }
523