cae6b37888f28bde21f82ee36684dbf2a55deb4c
[reactos.git] / reactos / drivers / video / displays / vga_new / enable.c
1 /*
2 * PROJECT: ReactOS Framebuffer Display Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/displays/framebuf/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 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 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 = (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 == (PPDEV) NULL)
116 {
117 RIP("DISP DrvEnablePDEV failed EngAllocMem\n");
118 return((DHPDEV) 0);
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((DHPDEV) 0);
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 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 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 DrvEnableSurface(
211 DHPDEV dhpdev)
212 {
213 PPDEV ppdev;
214 HSURF hsurf;
215 SIZEL sizl;
216 ULONG ulBitmapType;
217 FLONG flHooks;
218
219 // Create engine bitmap around frame buffer.
220
221 ppdev = (PPDEV) dhpdev;
222
223 if (!bInitSURF(ppdev, TRUE))
224 {
225 RIP("DISP DrvEnableSurface failed bInitSURF\n");
226 return(FALSE);
227 }
228
229 sizl.cx = ppdev->cxScreen;
230 sizl.cy = ppdev->cyScreen;
231
232 // eVb: 1.3 [VGARISC Change] - Disable dynamic palette and > 4BPP support
233 #if 0
234 if (ppdev->ulBitCount == 8)
235 {
236 if (!bInit256ColorPalette(ppdev)) {
237 RIP("DISP DrvEnableSurface failed to init the 8bpp palette\n");
238 return(FALSE);
239 }
240 ulBitmapType = BMF_8BPP;
241 flHooks = HOOKS_BMF8BPP;
242 }
243 else if (ppdev->ulBitCount == 16)
244 {
245 ulBitmapType = BMF_16BPP;
246 flHooks = HOOKS_BMF16BPP;
247 }
248 else if (ppdev->ulBitCount == 24)
249 {
250 ulBitmapType = BMF_24BPP;
251 flHooks = HOOKS_BMF24BPP;
252 }
253 else
254 {
255 ulBitmapType = BMF_32BPP;
256 flHooks = HOOKS_BMF32BPP;
257 }
258 // eVb: 1.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
259 ppdev->flHooks = flHooks;
260 // eVb: 1.3 [END]
261 #else
262 ulBitmapType = BMF_4BPP;
263 #endif
264 // eVb: 1.3 [END]
265 // eVb: 1.4 [DDK Change] - Use EngCreateDeviceSurface instead of EngCreateBitmap
266 hsurf = (HSURF)EngCreateDeviceSurface((DHSURF)ppdev,
267 sizl,
268 ulBitmapType);
269
270 if (hsurf == (HSURF) 0)
271 {
272 RIP("DISP DrvEnableSurface failed EngCreateDeviceSurface\n");
273 return(FALSE);
274 }
275 // eVb: 1.4 [END]
276
277 // eVb: 1.5 [DDK Change] - Use EngModifySurface instead of EngAssociateSurface
278 if ( !EngModifySurface(hsurf,
279 ppdev->hdevEng,
280 ppdev->flHooks | HOOK_SYNCHRONIZE,
281 MS_NOTSYSTEMMEMORY,
282 (DHSURF)ppdev,
283 ppdev->pjScreen,
284 ppdev->lDeltaScreen,
285 NULL))
286 {
287 RIP("DISP DrvEnableSurface failed EngModifySurface\n");
288 return(FALSE);
289 }
290 // eVb: 1.5 [END]
291 ppdev->hsurfEng = hsurf;
292 // eVb: 1.4 [VGARISC Change] - Allocate 4BPP DIB that will store GDI drawing
293 HSURF hSurfBitmap;
294 hSurfBitmap = (HSURF)EngCreateBitmap(sizl, 0, ulBitmapType, 0, NULL);
295 if (hSurfBitmap == (HSURF) 0)
296 {
297 RIP("DISP DrvEnableSurface failed EngCreateBitmap\n");
298 return(FALSE);
299 }
300
301 if ( !EngModifySurface(hSurfBitmap,
302 ppdev->hdevEng,
303 ppdev->flHooks | HOOK_SYNCHRONIZE,
304 MS_NOTSYSTEMMEMORY,
305 (DHSURF)ppdev,
306 ppdev->pjScreen,
307 ppdev->lDeltaScreen,
308 NULL))
309 {
310 RIP("DISP DrvEnableSurface failed second EngModifySurface\n");
311 return(FALSE);
312 }
313
314 ppdev->pso = EngLockSurface(hSurfBitmap);
315 if (ppdev->pso == NULL)
316 {
317 RIP("DISP DrvEnableSurface failed EngLockSurface\n");
318 return(FALSE);
319 }
320 // eVb: 1.4 [END]
321 return(hsurf);
322 }
323
324 /******************************Public*Routine******************************\
325 * DrvDisableSurface
326 *
327 * Free resources allocated by DrvEnableSurface. Release the surface.
328 *
329 \**************************************************************************/
330
331 VOID DrvDisableSurface(
332 DHPDEV dhpdev)
333 {
334 EngDeleteSurface(((PPDEV) dhpdev)->hsurfEng);
335 vDisableSURF((PPDEV) dhpdev);
336 ((PPDEV) dhpdev)->hsurfEng = (HSURF) 0;
337 }
338
339 /******************************Public*Routine******************************\
340 * DrvAssertMode
341 *
342 * This asks the device to reset itself to the mode of the pdev passed in.
343 *
344 \**************************************************************************/
345
346 BOOL DrvAssertMode(
347 DHPDEV dhpdev,
348 BOOL bEnable)
349 {
350 PPDEV ppdev = (PPDEV) dhpdev;
351 ULONG ulReturn;
352 PBYTE pjScreen;
353
354 if (bEnable)
355 {
356 //
357 // The screen must be reenabled, reinitialize the device to clean state.
358 //
359 // eVb: 1.6 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
360 pjScreen = ppdev->pjScreen;
361
362 if (!bInitSURF(ppdev, FALSE))
363 {
364 DISPDBG((0, "DISP DrvAssertMode failed bInitSURF\n"));
365 return (FALSE);
366 }
367
368 if (pjScreen != ppdev->pjScreen) {
369
370 if ( !EngModifySurface(ppdev->hsurfEng,
371 ppdev->hdevEng,
372 ppdev->flHooks | HOOK_SYNCHRONIZE,
373 MS_NOTSYSTEMMEMORY,
374 (DHSURF)ppdev,
375 ppdev->pjScreen,
376 ppdev->lDeltaScreen,
377 NULL))
378 {
379 DISPDBG((0, "DISP DrvAssertMode failed EngModifySurface\n"));
380 return (FALSE);
381 }
382 }
383 // eVb: 1.6 [END]
384 return (TRUE);
385 }
386 else
387 {
388 //
389 // We must give up the display.
390 // Call the kernel driver to reset the device to a known state.
391 //
392
393 if (EngDeviceIoControl(ppdev->hDriver,
394 IOCTL_VIDEO_RESET_DEVICE,
395 NULL,
396 0,
397 NULL,
398 0,
399 &ulReturn))
400 {
401 RIP("DISP DrvAssertMode failed IOCTL");
402 return FALSE;
403 }
404 else
405 {
406 return TRUE;
407 }
408 }
409 }
410
411 /******************************Public*Routine******************************\
412 * DrvGetModes
413 *
414 * Returns the list of available modes for the device.
415 *
416 \**************************************************************************/
417
418 ULONG DrvGetModes(
419 HANDLE hDriver,
420 ULONG cjSize,
421 DEVMODEW *pdm)
422
423 {
424
425 DWORD cModes;
426 DWORD cbOutputSize;
427 PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
428 DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
429 DWORD cbModeSize;
430
431 DISPDBG((3, "DrvGetModes\n"));
432
433 cModes = getAvailableModes(hDriver,
434 (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
435 &cbModeSize);
436
437 if (cModes == 0)
438 {
439 DISPDBG((0, "DrvGetModes failed to get mode information"));
440 return 0;
441 }
442
443 if (pdm == NULL)
444 {
445 cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
446 }
447 else
448 {
449 //
450 // Now copy the information for the supported modes back into the output
451 // buffer
452 //
453
454 cbOutputSize = 0;
455
456 pVideoTemp = pVideoModeInformation;
457
458 do
459 {
460 if (pVideoTemp->Length != 0)
461 {
462 if (cOutputModes == 0)
463 {
464 break;
465 }
466
467 //
468 // Zero the entire structure to start off with.
469 //
470
471 memset(pdm, 0, sizeof(DEVMODEW));
472
473 //
474 // Set the name of the device to the name of the DLL.
475 //
476
477 memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
478
479 pdm->dmSpecVersion = DM_SPECVERSION;
480 pdm->dmDriverVersion = DM_SPECVERSION;
481 pdm->dmSize = sizeof(DEVMODEW);
482 pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
483
484 pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
485 pVideoTemp->BitsPerPlane;
486 pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
487 pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
488 pdm->dmDisplayFrequency = pVideoTemp->Frequency;
489 pdm->dmDisplayFlags = 0;
490
491 pdm->dmFields = DM_BITSPERPEL |
492 DM_PELSWIDTH |
493 DM_PELSHEIGHT |
494 DM_DISPLAYFREQUENCY |
495 DM_DISPLAYFLAGS ;
496
497 //
498 // Go to the next DEVMODE entry in the buffer.
499 //
500
501 cOutputModes--;
502
503 pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
504 DRIVER_EXTRA_SIZE);
505
506 cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
507
508 }
509
510 pVideoTemp = (PVIDEO_MODE_INFORMATION)
511 (((PUCHAR)pVideoTemp) + cbModeSize);
512
513 } while (--cModes);
514 }
515
516 EngFreeMem(pVideoModeInformation);
517
518 return cbOutputSize;
519
520 }