reactos/win32ss/drivers/displays/vga_new/enable.c

523 lines
15 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS Framebuffer Display Driver
* LICENSE: Microsoft NT4 DDK Sample Code License
* FILE: win32ss/drivers/displays/vga_new/enable.c
* PURPOSE: Main Driver Initialization and PDEV Enabling
* PROGRAMMERS: Copyright (c) 1992-1995 Microsoft Corporation
* ReactOS Portable Systems Group
*/
#include "driver.h"
// The driver function table with all function index/address pairs
static DRVFN gadrvfn[] =
{
{ INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
{ INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
{ INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
{ INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
{ INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
{ INDEX_DrvAssertMode, (PFN) DrvAssertMode },
// eVb: 1.2 [VGARISC Change] - Disable hardware palette support
{ INDEX_DrvSetPalette, (PFN) DrvSetPalette },
// eVb: 1.2 [END]
// eVb: 1.1 [VGARISC Change] - Disable hardware pointer support
#if 0
{ INDEX_DrvMovePointer, (PFN) DrvMovePointer },
{ INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
#endif
// eVb: 1.1 [END]
{ INDEX_DrvGetModes, (PFN) DrvGetModes }
};
// Define the functions you want to hook for 8/16/24/32 pel formats
#define HOOKS_BMF8BPP 0
#define HOOKS_BMF16BPP 0
#define HOOKS_BMF24BPP 0
#define HOOKS_BMF32BPP 0
/******************************Public*Routine******************************\
* DrvEnableDriver
*
* Enables the driver by retrieving the drivers function table and version.
*
\**************************************************************************/
BOOL APIENTRY DrvEnableDriver(
ULONG iEngineVersion,
ULONG cj,
PDRVENABLEDATA pded)
{
// Engine Version is passed down so future drivers can support previous
// engine versions. A next generation driver can support both the old
// and new engine conventions if told what version of engine it is
// working with. For the first version the driver does nothing with it.
// eVb: 1.1 [DDK Change] - Remove bogus statement
//iEngineVersion;
// eVb: 1.1 [END]
// Fill in as much as we can.
if (cj >= sizeof(DRVENABLEDATA))
pded->pdrvfn = gadrvfn;
if (cj >= (sizeof(ULONG) * 2))
pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
// DDI version this driver was targeted for is passed back to engine.
// Future graphic's engine may break calls down to old driver format.
if (cj >= sizeof(ULONG))
// eVb: 1.2 [DDK Change] - Use DDI_DRIVER_VERSION_NT4 instead of DDI_DRIVER_VERSION
pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
// eVb: 1.2 [END]
return(TRUE);
}
/******************************Public*Routine******************************\
* DrvEnablePDEV
*
* DDI function, Enables the Physical Device.
*
* Return Value: device handle to pdev.
*
\**************************************************************************/
DHPDEV APIENTRY DrvEnablePDEV(
DEVMODEW *pDevmode, // Pointer to DEVMODE
PWSTR pwszLogAddress, // Logical address
ULONG cPatterns, // number of patterns
HSURF *ahsurfPatterns, // return standard patterns
ULONG cjGdiInfo, // Length of memory pointed to by pGdiInfo
ULONG *pGdiInfo, // Pointer to GdiInfo structure
ULONG cjDevInfo, // Length of following PDEVINFO structure
DEVINFO *pDevInfo, // physical device information structure
HDEV hdev, // HDEV, used for callbacks
PWSTR pwszDeviceName, // DeviceName - not used
HANDLE hDriver) // Handle to base driver
{
GDIINFO GdiInfo;
DEVINFO DevInfo;
PPDEV ppdev = (PPDEV) NULL;
UNREFERENCED_PARAMETER(pwszLogAddress);
UNREFERENCED_PARAMETER(pwszDeviceName);
// Allocate a physical device structure.
ppdev = (PPDEV) EngAllocMem(0, sizeof(PDEV), ALLOC_TAG);
if (ppdev == (PPDEV) NULL)
{
RIP("DISP DrvEnablePDEV failed EngAllocMem\n");
return((DHPDEV) 0);
}
memset(ppdev, 0, sizeof(PDEV));
// Save the screen handle in the PDEV.
ppdev->hDriver = hDriver;
// Get the current screen mode information. Set up device caps and devinfo.
if (!bInitPDEV(ppdev, pDevmode, &GdiInfo, &DevInfo))
{
DISPDBG((0,"DISP DrvEnablePDEV failed\n"));
goto error_free;
}
// eVb: 1.2 [VGARISC Change] - Disable hardware pointer support
#if 0
// Initialize the cursor information.
if (!bInitPointer(ppdev, &DevInfo))
{
// Not a fatal error...
DISPDBG((0, "DrvEnablePDEV failed bInitPointer\n"));
}
#endif
// eVb: 1.2 [END]
// Initialize palette information.
if (!bInitPaletteInfo(ppdev, &DevInfo))
{
RIP("DrvEnablePDEV failed bInitPalette\n");
goto error_free;
}
// Copy the devinfo into the engine buffer.
memcpy(pDevInfo, &DevInfo, min(sizeof(DEVINFO), cjDevInfo));
// Set the pdevCaps with GdiInfo we have prepared to the list of caps for this
// pdev.
memcpy(pGdiInfo, &GdiInfo, min(cjGdiInfo, sizeof(GDIINFO)));
return((DHPDEV) ppdev);
// Error case for failure.
error_free:
EngFreeMem(ppdev);
return((DHPDEV) 0);
}
/******************************Public*Routine******************************\
* DrvCompletePDEV
*
* Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
*
\**************************************************************************/
VOID APIENTRY DrvCompletePDEV(
DHPDEV dhpdev,
HDEV hdev)
{
((PPDEV) dhpdev)->hdevEng = hdev;
}
/******************************Public*Routine******************************\
* DrvDisablePDEV
*
* Release the resources allocated in DrvEnablePDEV. If a surface has been
* enabled DrvDisableSurface will have already been called.
*
\**************************************************************************/
VOID APIENTRY DrvDisablePDEV(
DHPDEV dhpdev)
{
vDisablePalette((PPDEV) dhpdev);
EngFreeMem(dhpdev);
}
/******************************Public*Routine******************************\
* DrvEnableSurface
*
* Enable the surface for the device. Hook the calls this driver supports.
*
* Return: Handle to the surface if successful, 0 for failure.
*
\**************************************************************************/
HSURF APIENTRY DrvEnableSurface(
DHPDEV dhpdev)
{
PPDEV ppdev;
HSURF hsurf;
SIZEL sizl;
ULONG ulBitmapType;
#if 0
FLONG flHooks;
#endif
HSURF hSurfBitmap;
// Create engine bitmap around frame buffer.
ppdev = (PPDEV) dhpdev;
if (!bInitSURF(ppdev, TRUE))
{
RIP("DISP DrvEnableSurface failed bInitSURF\n");
return(FALSE);
}
sizl.cx = ppdev->cxScreen;
sizl.cy = ppdev->cyScreen;
// eVb: 1.3 [VGARISC Change] - Disable dynamic palette and > 4BPP support
#if 0
if (ppdev->ulBitCount == 8)
{
if (!bInit256ColorPalette(ppdev)) {
RIP("DISP DrvEnableSurface failed to init the 8bpp palette\n");
return(FALSE);
}
ulBitmapType = BMF_8BPP;
flHooks = HOOKS_BMF8BPP;
}
else if (ppdev->ulBitCount == 16)
{
ulBitmapType = BMF_16BPP;
flHooks = HOOKS_BMF16BPP;
}
else if (ppdev->ulBitCount == 24)
{
ulBitmapType = BMF_24BPP;
flHooks = HOOKS_BMF24BPP;
}
else
{
ulBitmapType = BMF_32BPP;
flHooks = HOOKS_BMF32BPP;
}
// eVb: 1.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
ppdev->flHooks = flHooks;
// eVb: 1.3 [END]
#else
ulBitmapType = BMF_4BPP;
#endif
// eVb: 1.3 [END]
// eVb: 1.4 [DDK Change] - Use EngCreateDeviceSurface instead of EngCreateBitmap
hsurf = (HSURF)EngCreateDeviceSurface((DHSURF)ppdev,
sizl,
ulBitmapType);
if (hsurf == (HSURF) 0)
{
RIP("DISP DrvEnableSurface failed EngCreateDeviceSurface\n");
return(FALSE);
}
// eVb: 1.4 [END]
// eVb: 1.5 [DDK Change] - Use EngModifySurface instead of EngAssociateSurface
if ( !EngModifySurface(hsurf,
ppdev->hdevEng,
ppdev->flHooks | HOOK_SYNCHRONIZE,
MS_NOTSYSTEMMEMORY,
(DHSURF)ppdev,
ppdev->pjScreen,
ppdev->lDeltaScreen,
NULL))
{
RIP("DISP DrvEnableSurface failed EngModifySurface\n");
return(FALSE);
}
// eVb: 1.5 [END]
ppdev->hsurfEng = hsurf;
// eVb: 1.4 [VGARISC Change] - Allocate 4BPP DIB that will store GDI drawing
hSurfBitmap = (HSURF)EngCreateBitmap(sizl, 0, ulBitmapType, 0, NULL);
if (hSurfBitmap == (HSURF) 0)
{
RIP("DISP DrvEnableSurface failed EngCreateBitmap\n");
return(FALSE);
}
if ( !EngModifySurface(hSurfBitmap,
ppdev->hdevEng,
ppdev->flHooks | HOOK_SYNCHRONIZE,
MS_NOTSYSTEMMEMORY,
(DHSURF)ppdev,
ppdev->pjScreen,
ppdev->lDeltaScreen,
NULL))
{
RIP("DISP DrvEnableSurface failed second EngModifySurface\n");
return(FALSE);
}
ppdev->pso = EngLockSurface(hSurfBitmap);
if (ppdev->pso == NULL)
{
RIP("DISP DrvEnableSurface failed EngLockSurface\n");
return(FALSE);
}
// eVb: 1.4 [END]
return(hsurf);
}
/******************************Public*Routine******************************\
* DrvDisableSurface
*
* Free resources allocated by DrvEnableSurface. Release the surface.
*
\**************************************************************************/
VOID APIENTRY DrvDisableSurface(
DHPDEV dhpdev)
{
EngDeleteSurface(((PPDEV) dhpdev)->hsurfEng);
vDisableSURF((PPDEV) dhpdev);
((PPDEV) dhpdev)->hsurfEng = (HSURF) 0;
}
/******************************Public*Routine******************************\
* DrvAssertMode
*
* This asks the device to reset itself to the mode of the pdev passed in.
*
\**************************************************************************/
BOOL APIENTRY DrvAssertMode(
DHPDEV dhpdev,
BOOL bEnable)
{
PPDEV ppdev = (PPDEV) dhpdev;
ULONG ulReturn;
PBYTE pjScreen;
if (bEnable)
{
//
// The screen must be reenabled, reinitialize the device to clean state.
//
// eVb: 1.6 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
pjScreen = ppdev->pjScreen;
if (!bInitSURF(ppdev, FALSE))
{
DISPDBG((0, "DISP DrvAssertMode failed bInitSURF\n"));
return (FALSE);
}
if (pjScreen != ppdev->pjScreen) {
if ( !EngModifySurface(ppdev->hsurfEng,
ppdev->hdevEng,
ppdev->flHooks | HOOK_SYNCHRONIZE,
MS_NOTSYSTEMMEMORY,
(DHSURF)ppdev,
ppdev->pjScreen,
ppdev->lDeltaScreen,
NULL))
{
DISPDBG((0, "DISP DrvAssertMode failed EngModifySurface\n"));
return (FALSE);
}
}
// eVb: 1.6 [END]
return (TRUE);
}
else
{
//
// We must give up the display.
// Call the kernel driver to reset the device to a known state.
//
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_RESET_DEVICE,
NULL,
0,
NULL,
0,
&ulReturn))
{
RIP("DISP DrvAssertMode failed IOCTL");
return FALSE;
}
else
{
return TRUE;
}
}
}
/******************************Public*Routine******************************\
* DrvGetModes
*
* Returns the list of available modes for the device.
*
\**************************************************************************/
ULONG APIENTRY DrvGetModes(
HANDLE hDriver,
ULONG cjSize,
DEVMODEW *pdm)
{
DWORD cModes;
DWORD cbOutputSize;
PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
DWORD cbModeSize;
DISPDBG((3, "DrvGetModes\n"));
cModes = getAvailableModes(hDriver,
(PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
&cbModeSize);
if (cModes == 0)
{
DISPDBG((0, "DrvGetModes failed to get mode information"));
return 0;
}
if (pdm == NULL)
{
cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
}
else
{
//
// Now copy the information for the supported modes back into the output
// buffer
//
cbOutputSize = 0;
pVideoTemp = pVideoModeInformation;
do
{
if (pVideoTemp->Length != 0)
{
if (cOutputModes == 0)
{
break;
}
//
// Zero the entire structure to start off with.
//
memset(pdm, 0, sizeof(DEVMODEW));
//
// Set the name of the device to the name of the DLL.
//
memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
pdm->dmSpecVersion = DM_SPECVERSION;
pdm->dmDriverVersion = DM_SPECVERSION;
pdm->dmSize = sizeof(DEVMODEW);
pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
pVideoTemp->BitsPerPlane;
pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
pdm->dmDisplayFrequency = pVideoTemp->Frequency;
pdm->dmDisplayFlags = 0;
pdm->dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY |
DM_DISPLAYFLAGS ;
//
// Go to the next DEVMODE entry in the buffer.
//
cOutputModes--;
pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
DRIVER_EXTRA_SIZE);
cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
}
pVideoTemp = (PVIDEO_MODE_INFORMATION)
(((PUCHAR)pVideoTemp) + cbModeSize);
} while (--cModes);
}
EngFreeMem(pVideoModeInformation);
return cbOutputSize;
}