/* * PROJECT: ReactOS Framebuffer Display Driver * LICENSE: Microsoft NT4 DDK Sample Code License * FILE: boot/drivers/video/displays/framebuf/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 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 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 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 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 DrvEnableSurface( DHPDEV dhpdev) { PPDEV ppdev; HSURF hsurf; SIZEL sizl; ULONG ulBitmapType; FLONG flHooks; // 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 HSURF hSurfBitmap; 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 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 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 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; }