127cd9eafSDmitry Borisov /* 227cd9eafSDmitry Borisov * PROJECT: ReactOS framebuffer driver for NEC PC-98 series 327cd9eafSDmitry Borisov * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 427cd9eafSDmitry Borisov * PURPOSE: Miniport driver entrypoint 527cd9eafSDmitry Borisov * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com) 627cd9eafSDmitry Borisov */ 727cd9eafSDmitry Borisov 827cd9eafSDmitry Borisov /* INCLUDES *******************************************************************/ 927cd9eafSDmitry Borisov 1027cd9eafSDmitry Borisov #include "pc98vid.h" 1127cd9eafSDmitry Borisov 1227cd9eafSDmitry Borisov /* GLOBALS ********************************************************************/ 1327cd9eafSDmitry Borisov 1427cd9eafSDmitry Borisov const VIDEOMODE VideoModes[] = 1527cd9eafSDmitry Borisov { 1627cd9eafSDmitry Borisov {640, 480, GRAPH_HF_31KHZ, GDC2_CLOCK1_5MHZ, GDC2_CLOCK2_5MHZ, 1727cd9eafSDmitry Borisov GDC2_MODE_LINES_800, 60, 1827cd9eafSDmitry Borisov {0, 80, 12, 2, 4, 4, 6, 480, 37}, {0, 80, 12, 2, 4, 132, 6, 480, 37}} 1927cd9eafSDmitry Borisov }; 2027cd9eafSDmitry Borisov 2127cd9eafSDmitry Borisov static VIDEO_ACCESS_RANGE LegacyRangeList[] = 2227cd9eafSDmitry Borisov { 2327cd9eafSDmitry Borisov { {{0x60, 0}}, 0x00000001, 1, 1, 1, 0 }, 2427cd9eafSDmitry Borisov { {{0x62, 0}}, 0x00000001, 1, 1, 1, 0 }, 2527cd9eafSDmitry Borisov { {{0x68, 0}}, 0x00000001, 1, 1, 1, 0 }, 2627cd9eafSDmitry Borisov { {{0x6A, 0}}, 0x00000001, 1, 1, 1, 0 }, 2727cd9eafSDmitry Borisov { {{0x7C, 0}}, 0x00000001, 1, 1, 1, 0 }, 2827cd9eafSDmitry Borisov { {{0xA0, 0}}, 0x00000001, 1, 1, 1, 0 }, 2927cd9eafSDmitry Borisov { {{0xA2, 0}}, 0x00000001, 1, 1, 1, 0 }, 3027cd9eafSDmitry Borisov { {{0xA4, 0}}, 0x00000001, 1, 1, 1, 0 }, 3127cd9eafSDmitry Borisov { {{0xA6, 0}}, 0x00000001, 1, 1, 1, 0 }, 3227cd9eafSDmitry Borisov { {{0xA8, 0}}, 0x00000001, 1, 1, 1, 0 }, 3327cd9eafSDmitry Borisov { {{0xAA, 0}}, 0x00000001, 1, 1, 1, 0 }, 3427cd9eafSDmitry Borisov { {{0xAC, 0}}, 0x00000001, 1, 1, 1, 0 }, 3527cd9eafSDmitry Borisov { {{0xAE, 0}}, 0x00000001, 1, 1, 1, 0 }, 3627cd9eafSDmitry Borisov { {{0x9A0, 0}}, 0x00000001, 1, 1, 1, 0 }, 3727cd9eafSDmitry Borisov { {{0x9A2, 0}}, 0x00000001, 1, 1, 1, 0 }, 3827cd9eafSDmitry Borisov { {{0x9A8, 0}}, 0x00000001, 1, 1, 1, 0 }, 3927cd9eafSDmitry Borisov { {{0xFAC, 0}}, 0x00000001, 1, 1, 1, 0 }, 4027cd9eafSDmitry Borisov { {{VRAM_NORMAL_PLANE_I, 0}}, PEGC_CONTROL_SIZE, 0, 0, 1, 0 }, 4127cd9eafSDmitry Borisov { {{PEGC_FRAMEBUFFER_PACKED, 0}}, PEGC_FRAMEBUFFER_SIZE, 0, 0, 1, 0 } 4227cd9eafSDmitry Borisov }; 4327cd9eafSDmitry Borisov #define CONTROL_RANGE_INDEX 17 4427cd9eafSDmitry Borisov #define FRAMEBUFFER_RANGE_INDEX 18 4527cd9eafSDmitry Borisov 4627cd9eafSDmitry Borisov /* FUNCTIONS ******************************************************************/ 4727cd9eafSDmitry Borisov 48*5c7ce447SVictor Perevertkin CODE_SEG("PAGE") 4927cd9eafSDmitry Borisov VP_STATUS 5027cd9eafSDmitry Borisov NTAPI 5127cd9eafSDmitry Borisov Pc98VidFindAdapter( 5227cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension, 5327cd9eafSDmitry Borisov _In_opt_ PVOID HwContext, 5427cd9eafSDmitry Borisov _In_opt_ PWSTR ArgumentString, 5527cd9eafSDmitry Borisov _Inout_ PVIDEO_PORT_CONFIG_INFO ConfigInfo, 5627cd9eafSDmitry Borisov _Out_ PUCHAR Again) 5727cd9eafSDmitry Borisov { 5827cd9eafSDmitry Borisov VP_STATUS Status; 5927cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 6027cd9eafSDmitry Borisov ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; 6127cd9eafSDmitry Borisov static WCHAR AdapterChipType[] = L"Onboard"; 6227cd9eafSDmitry Borisov static WCHAR AdapterDacType[] = L"8 bit"; 6327cd9eafSDmitry Borisov static WCHAR AdapterString[] = L"PEGC"; 6427cd9eafSDmitry Borisov 6527cd9eafSDmitry Borisov PAGED_CODE(); 6627cd9eafSDmitry Borisov 6727cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s()\n", __FUNCTION__)); 6827cd9eafSDmitry Borisov 6927cd9eafSDmitry Borisov if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) 7027cd9eafSDmitry Borisov return ERROR_INVALID_PARAMETER; 7127cd9eafSDmitry Borisov 7227cd9eafSDmitry Borisov Status = VideoPortVerifyAccessRanges(DeviceExtension, 7327cd9eafSDmitry Borisov RTL_NUMBER_OF(LegacyRangeList), 7427cd9eafSDmitry Borisov LegacyRangeList); 7527cd9eafSDmitry Borisov if (Status != NO_ERROR) 7627cd9eafSDmitry Borisov { 7727cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Resource conflict was found\n", __FUNCTION__)); 7827cd9eafSDmitry Borisov 7927cd9eafSDmitry Borisov return ERROR_INVALID_PARAMETER; 8027cd9eafSDmitry Borisov } 8127cd9eafSDmitry Borisov 8227cd9eafSDmitry Borisov DeviceExtension->PegcControl = LegacyRangeList[CONTROL_RANGE_INDEX].RangeStart; 8327cd9eafSDmitry Borisov DeviceExtension->PegcControlLength = LegacyRangeList[CONTROL_RANGE_INDEX].RangeLength; 8427cd9eafSDmitry Borisov DeviceExtension->FrameBuffer = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeStart; 8527cd9eafSDmitry Borisov DeviceExtension->FrameBufferLength = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeLength; 8627cd9eafSDmitry Borisov 8727cd9eafSDmitry Borisov Status = VideoPortMapMemory(DeviceExtension, 8827cd9eafSDmitry Borisov DeviceExtension->PegcControl, 8927cd9eafSDmitry Borisov &DeviceExtension->PegcControlLength, 9027cd9eafSDmitry Borisov &inIoSpace, 9127cd9eafSDmitry Borisov (PVOID)&DeviceExtension->PegcControlVa); 9227cd9eafSDmitry Borisov if (Status != NO_ERROR) 9327cd9eafSDmitry Borisov { 9427cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Failed to map control memory\n", __FUNCTION__)); 9527cd9eafSDmitry Borisov 9627cd9eafSDmitry Borisov VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL); 9727cd9eafSDmitry Borisov 9827cd9eafSDmitry Borisov return ERROR_DEV_NOT_EXIST; 9927cd9eafSDmitry Borisov } 10027cd9eafSDmitry Borisov 10127cd9eafSDmitry Borisov if (!HasPegcController(DeviceExtension)) 10227cd9eafSDmitry Borisov { 10327cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Unsupported hardware\n", __FUNCTION__)); 10427cd9eafSDmitry Borisov 10527cd9eafSDmitry Borisov VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL); 10627cd9eafSDmitry Borisov VideoPortUnmapMemory(DeviceExtension, 10727cd9eafSDmitry Borisov (PVOID)DeviceExtension->PegcControlVa, 10827cd9eafSDmitry Borisov NULL); 10927cd9eafSDmitry Borisov 11027cd9eafSDmitry Borisov return ERROR_DEV_NOT_EXIST; 11127cd9eafSDmitry Borisov } 11227cd9eafSDmitry Borisov 11327cd9eafSDmitry Borisov /* Not VGA-compatible */ 11427cd9eafSDmitry Borisov ConfigInfo->NumEmulatorAccessEntries = 0; 11527cd9eafSDmitry Borisov ConfigInfo->EmulatorAccessEntries = NULL; 11627cd9eafSDmitry Borisov ConfigInfo->EmulatorAccessEntriesContext = 0; 11727cd9eafSDmitry Borisov ConfigInfo->HardwareStateSize = 0; 11827cd9eafSDmitry Borisov ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0; 11927cd9eafSDmitry Borisov ConfigInfo->VdmPhysicalVideoMemoryLength = 0; 12027cd9eafSDmitry Borisov 12127cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension, 12227cd9eafSDmitry Borisov L"HardwareInformation.ChipType", 12327cd9eafSDmitry Borisov AdapterChipType, 12427cd9eafSDmitry Borisov sizeof(AdapterChipType)); 12527cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension, 12627cd9eafSDmitry Borisov L"HardwareInformation.DacType", 12727cd9eafSDmitry Borisov AdapterDacType, 12827cd9eafSDmitry Borisov sizeof(AdapterDacType)); 12927cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension, 13027cd9eafSDmitry Borisov L"HardwareInformation.MemorySize", 13127cd9eafSDmitry Borisov &DeviceExtension->FrameBufferLength, 13227cd9eafSDmitry Borisov sizeof(ULONG)); 13327cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension, 13427cd9eafSDmitry Borisov L"HardwareInformation.AdapterString", 13527cd9eafSDmitry Borisov AdapterString, 13627cd9eafSDmitry Borisov sizeof(AdapterString)); 13727cd9eafSDmitry Borisov 13827cd9eafSDmitry Borisov return NO_ERROR; 13927cd9eafSDmitry Borisov } 14027cd9eafSDmitry Borisov 141*5c7ce447SVictor Perevertkin CODE_SEG("PAGE") 14227cd9eafSDmitry Borisov BOOLEAN 14327cd9eafSDmitry Borisov NTAPI 14427cd9eafSDmitry Borisov Pc98VidInitialize( 14527cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension) 14627cd9eafSDmitry Borisov { 14727cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 14827cd9eafSDmitry Borisov 14927cd9eafSDmitry Borisov PAGED_CODE(); 15027cd9eafSDmitry Borisov 15127cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s()\n", __FUNCTION__)); 15227cd9eafSDmitry Borisov 15327cd9eafSDmitry Borisov DeviceExtension->ModeCount = RTL_NUMBER_OF(VideoModes); 15427cd9eafSDmitry Borisov DeviceExtension->MonitorCount = 1; 15527cd9eafSDmitry Borisov 15627cd9eafSDmitry Borisov return TRUE; 15727cd9eafSDmitry Borisov } 15827cd9eafSDmitry Borisov 159*5c7ce447SVictor Perevertkin CODE_SEG("PAGE") 16027cd9eafSDmitry Borisov VP_STATUS 16127cd9eafSDmitry Borisov NTAPI 16227cd9eafSDmitry Borisov Pc98VidGetVideoChildDescriptor( 16327cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension, 16427cd9eafSDmitry Borisov _In_ PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, 16527cd9eafSDmitry Borisov _Out_ PVIDEO_CHILD_TYPE VideoChildType, 16627cd9eafSDmitry Borisov _Out_ PUCHAR pChildDescriptor, 16727cd9eafSDmitry Borisov _Out_ PULONG UId, 16827cd9eafSDmitry Borisov _Out_ PULONG pUnused) 16927cd9eafSDmitry Borisov { 17027cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 17127cd9eafSDmitry Borisov 17227cd9eafSDmitry Borisov UNREFERENCED_PARAMETER(pChildDescriptor); 17327cd9eafSDmitry Borisov 17427cd9eafSDmitry Borisov PAGED_CODE(); 17527cd9eafSDmitry Borisov 17627cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s() Index %d\n", 17727cd9eafSDmitry Borisov __FUNCTION__, ChildEnumInfo->ChildIndex)); 17827cd9eafSDmitry Borisov 17927cd9eafSDmitry Borisov *pUnused = 0; 18027cd9eafSDmitry Borisov 18127cd9eafSDmitry Borisov if (ChildEnumInfo->ChildIndex > 0 && 18227cd9eafSDmitry Borisov ChildEnumInfo->ChildIndex <= DeviceExtension->MonitorCount) 18327cd9eafSDmitry Borisov { 18427cd9eafSDmitry Borisov *VideoChildType = Monitor; 18527cd9eafSDmitry Borisov *UId = MONITOR_HW_ID; 18627cd9eafSDmitry Borisov 18727cd9eafSDmitry Borisov return VIDEO_ENUM_MORE_DEVICES; 18827cd9eafSDmitry Borisov } 18927cd9eafSDmitry Borisov 19027cd9eafSDmitry Borisov return ERROR_NO_MORE_DEVICES; 19127cd9eafSDmitry Borisov } 19227cd9eafSDmitry Borisov 193*5c7ce447SVictor Perevertkin CODE_SEG("INIT") 19427cd9eafSDmitry Borisov ULONG 19527cd9eafSDmitry Borisov NTAPI 19627cd9eafSDmitry Borisov DriverEntry( 19727cd9eafSDmitry Borisov _In_ PVOID Context1, 19827cd9eafSDmitry Borisov _In_ PVOID Context2) 19927cd9eafSDmitry Borisov { 20027cd9eafSDmitry Borisov VIDEO_HW_INITIALIZATION_DATA InitData; 20127cd9eafSDmitry Borisov ULONG Status; 20227cd9eafSDmitry Borisov BOOLEAN IsLiveCd; 20327cd9eafSDmitry Borisov 20427cd9eafSDmitry Borisov VideoDebugPrint((Trace, "(%s:%d) %s()\n", 20527cd9eafSDmitry Borisov __FILE__, __LINE__, __FUNCTION__)); 20627cd9eafSDmitry Borisov 20727cd9eafSDmitry Borisov // FIXME: Detect IsLiveCd 20827cd9eafSDmitry Borisov IsLiveCd = TRUE; 20927cd9eafSDmitry Borisov 21027cd9eafSDmitry Borisov VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); 21127cd9eafSDmitry Borisov InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); 21227cd9eafSDmitry Borisov InitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 21327cd9eafSDmitry Borisov InitData.HwFindAdapter = Pc98VidFindAdapter; 21427cd9eafSDmitry Borisov InitData.HwInitialize = Pc98VidInitialize; 21527cd9eafSDmitry Borisov InitData.HwStartIO = Pc98VidStartIO; 21627cd9eafSDmitry Borisov /* 21727cd9eafSDmitry Borisov * On LiveCD, we expect to see the initialized video 21827cd9eafSDmitry Borisov * before starting the device enumeration, 21927cd9eafSDmitry Borisov * so we should mark the driver as non-PnP miniport. 22027cd9eafSDmitry Borisov */ 22127cd9eafSDmitry Borisov if (!IsLiveCd) 22227cd9eafSDmitry Borisov { 22327cd9eafSDmitry Borisov InitData.HwGetPowerState = Pc98VidGetPowerState; 22427cd9eafSDmitry Borisov InitData.HwSetPowerState = Pc98VidSetPowerState; 22527cd9eafSDmitry Borisov InitData.HwGetVideoChildDescriptor = Pc98VidGetVideoChildDescriptor; 22627cd9eafSDmitry Borisov } 22727cd9eafSDmitry Borisov 22827cd9eafSDmitry Borisov InitData.HwLegacyResourceList = LegacyRangeList; 22927cd9eafSDmitry Borisov InitData.HwLegacyResourceCount = RTL_NUMBER_OF(LegacyRangeList); 23027cd9eafSDmitry Borisov 23127cd9eafSDmitry Borisov InitData.AdapterInterfaceType = Isa; 23227cd9eafSDmitry Borisov 23327cd9eafSDmitry Borisov Status = VideoPortInitialize(Context1, Context2, &InitData, NULL); 23427cd9eafSDmitry Borisov if (!NT_SUCCESS(Status)) 23527cd9eafSDmitry Borisov { 23627cd9eafSDmitry Borisov VideoDebugPrint((Error, "(%s:%d) %s() Initialization failed 0x%lX\n", 23727cd9eafSDmitry Borisov __FILE__, __LINE__, __FUNCTION__, Status)); 23827cd9eafSDmitry Borisov } 23927cd9eafSDmitry Borisov 24027cd9eafSDmitry Borisov return Status; 24127cd9eafSDmitry Borisov } 242