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
14*f7d825e6SDmitry Borisov DATA_SEG("PAGECONS")
1527cd9eafSDmitry Borisov const VIDEOMODE VideoModes[] =
1627cd9eafSDmitry Borisov {
1727cd9eafSDmitry Borisov {640, 480, GRAPH_HF_31KHZ, GDC2_CLOCK1_5MHZ, GDC2_CLOCK2_5MHZ,
1827cd9eafSDmitry Borisov GDC2_MODE_LINES_800, 60,
1927cd9eafSDmitry Borisov {0, 80, 12, 2, 4, 4, 6, 480, 37}, {0, 80, 12, 2, 4, 132, 6, 480, 37}}
2027cd9eafSDmitry Borisov };
2127cd9eafSDmitry Borisov
22*f7d825e6SDmitry Borisov DATA_SEG("PAGECONS")
23*f7d825e6SDmitry Borisov const VIDEO_ACCESS_RANGE LegacyRangeList[] =
2427cd9eafSDmitry Borisov {
2527cd9eafSDmitry Borisov { {{0x60, 0}}, 0x00000001, 1, 1, 1, 0 },
2627cd9eafSDmitry Borisov { {{0x62, 0}}, 0x00000001, 1, 1, 1, 0 },
2727cd9eafSDmitry Borisov { {{0x68, 0}}, 0x00000001, 1, 1, 1, 0 },
2827cd9eafSDmitry Borisov { {{0x6A, 0}}, 0x00000001, 1, 1, 1, 0 },
2927cd9eafSDmitry Borisov { {{0x7C, 0}}, 0x00000001, 1, 1, 1, 0 },
3027cd9eafSDmitry Borisov { {{0xA0, 0}}, 0x00000001, 1, 1, 1, 0 },
3127cd9eafSDmitry Borisov { {{0xA2, 0}}, 0x00000001, 1, 1, 1, 0 },
3227cd9eafSDmitry Borisov { {{0xA4, 0}}, 0x00000001, 1, 1, 1, 0 },
3327cd9eafSDmitry Borisov { {{0xA6, 0}}, 0x00000001, 1, 1, 1, 0 },
3427cd9eafSDmitry Borisov { {{0xA8, 0}}, 0x00000001, 1, 1, 1, 0 },
3527cd9eafSDmitry Borisov { {{0xAA, 0}}, 0x00000001, 1, 1, 1, 0 },
3627cd9eafSDmitry Borisov { {{0xAC, 0}}, 0x00000001, 1, 1, 1, 0 },
3727cd9eafSDmitry Borisov { {{0xAE, 0}}, 0x00000001, 1, 1, 1, 0 },
3827cd9eafSDmitry Borisov { {{0x9A0, 0}}, 0x00000001, 1, 1, 1, 0 },
3927cd9eafSDmitry Borisov { {{0x9A2, 0}}, 0x00000001, 1, 1, 1, 0 },
4027cd9eafSDmitry Borisov { {{0x9A8, 0}}, 0x00000001, 1, 1, 1, 0 },
4127cd9eafSDmitry Borisov { {{0xFAC, 0}}, 0x00000001, 1, 1, 1, 0 },
4227cd9eafSDmitry Borisov { {{VRAM_NORMAL_PLANE_I, 0}}, PEGC_CONTROL_SIZE, 0, 0, 1, 0 },
4327cd9eafSDmitry Borisov { {{PEGC_FRAMEBUFFER_PACKED, 0}}, PEGC_FRAMEBUFFER_SIZE, 0, 0, 1, 0 }
4427cd9eafSDmitry Borisov };
4527cd9eafSDmitry Borisov #define CONTROL_RANGE_INDEX 17
4627cd9eafSDmitry Borisov #define FRAMEBUFFER_RANGE_INDEX 18
4727cd9eafSDmitry Borisov
4827cd9eafSDmitry Borisov /* FUNCTIONS ******************************************************************/
4927cd9eafSDmitry Borisov
504dc31254SDmitry Borisov static
515c7ce447SVictor Perevertkin CODE_SEG("PAGE")
5227cd9eafSDmitry Borisov VP_STATUS
5327cd9eafSDmitry Borisov NTAPI
Pc98VidFindAdapter(_In_ PVOID HwDeviceExtension,_In_opt_ PVOID HwContext,_In_opt_ PWSTR ArgumentString,_Inout_ PVIDEO_PORT_CONFIG_INFO ConfigInfo,_Out_ PUCHAR Again)5427cd9eafSDmitry Borisov Pc98VidFindAdapter(
5527cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension,
5627cd9eafSDmitry Borisov _In_opt_ PVOID HwContext,
5727cd9eafSDmitry Borisov _In_opt_ PWSTR ArgumentString,
5827cd9eafSDmitry Borisov _Inout_ PVIDEO_PORT_CONFIG_INFO ConfigInfo,
5927cd9eafSDmitry Borisov _Out_ PUCHAR Again)
6027cd9eafSDmitry Borisov {
6127cd9eafSDmitry Borisov VP_STATUS Status;
6227cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
6327cd9eafSDmitry Borisov ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY;
6427cd9eafSDmitry Borisov static WCHAR AdapterChipType[] = L"Onboard";
6527cd9eafSDmitry Borisov static WCHAR AdapterDacType[] = L"8 bit";
6627cd9eafSDmitry Borisov static WCHAR AdapterString[] = L"PEGC";
6727cd9eafSDmitry Borisov
6827cd9eafSDmitry Borisov PAGED_CODE();
6927cd9eafSDmitry Borisov
7027cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s()\n", __FUNCTION__));
7127cd9eafSDmitry Borisov
7227cd9eafSDmitry Borisov if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO))
7327cd9eafSDmitry Borisov return ERROR_INVALID_PARAMETER;
7427cd9eafSDmitry Borisov
7527cd9eafSDmitry Borisov Status = VideoPortVerifyAccessRanges(DeviceExtension,
7627cd9eafSDmitry Borisov RTL_NUMBER_OF(LegacyRangeList),
77*f7d825e6SDmitry Borisov (PVIDEO_ACCESS_RANGE)LegacyRangeList);
7827cd9eafSDmitry Borisov if (Status != NO_ERROR)
7927cd9eafSDmitry Borisov {
8027cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Resource conflict was found\n", __FUNCTION__));
8127cd9eafSDmitry Borisov
8227cd9eafSDmitry Borisov return ERROR_INVALID_PARAMETER;
8327cd9eafSDmitry Borisov }
8427cd9eafSDmitry Borisov
8527cd9eafSDmitry Borisov DeviceExtension->PegcControl = LegacyRangeList[CONTROL_RANGE_INDEX].RangeStart;
8627cd9eafSDmitry Borisov DeviceExtension->PegcControlLength = LegacyRangeList[CONTROL_RANGE_INDEX].RangeLength;
8727cd9eafSDmitry Borisov DeviceExtension->FrameBuffer = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeStart;
8827cd9eafSDmitry Borisov DeviceExtension->FrameBufferLength = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeLength;
8927cd9eafSDmitry Borisov
9027cd9eafSDmitry Borisov Status = VideoPortMapMemory(DeviceExtension,
9127cd9eafSDmitry Borisov DeviceExtension->PegcControl,
9227cd9eafSDmitry Borisov &DeviceExtension->PegcControlLength,
9327cd9eafSDmitry Borisov &inIoSpace,
9427cd9eafSDmitry Borisov (PVOID)&DeviceExtension->PegcControlVa);
9527cd9eafSDmitry Borisov if (Status != NO_ERROR)
9627cd9eafSDmitry Borisov {
9727cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Failed to map control memory\n", __FUNCTION__));
9827cd9eafSDmitry Borisov
9927cd9eafSDmitry Borisov VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL);
10027cd9eafSDmitry Borisov
10127cd9eafSDmitry Borisov return ERROR_DEV_NOT_EXIST;
10227cd9eafSDmitry Borisov }
10327cd9eafSDmitry Borisov
10427cd9eafSDmitry Borisov if (!HasPegcController(DeviceExtension))
10527cd9eafSDmitry Borisov {
10627cd9eafSDmitry Borisov VideoDebugPrint((Error, "%s() Unsupported hardware\n", __FUNCTION__));
10727cd9eafSDmitry Borisov
10827cd9eafSDmitry Borisov VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL);
10927cd9eafSDmitry Borisov VideoPortUnmapMemory(DeviceExtension,
11027cd9eafSDmitry Borisov (PVOID)DeviceExtension->PegcControlVa,
11127cd9eafSDmitry Borisov NULL);
11227cd9eafSDmitry Borisov
11327cd9eafSDmitry Borisov return ERROR_DEV_NOT_EXIST;
11427cd9eafSDmitry Borisov }
11527cd9eafSDmitry Borisov
11627cd9eafSDmitry Borisov /* Not VGA-compatible */
11727cd9eafSDmitry Borisov ConfigInfo->NumEmulatorAccessEntries = 0;
11827cd9eafSDmitry Borisov ConfigInfo->EmulatorAccessEntries = NULL;
11927cd9eafSDmitry Borisov ConfigInfo->EmulatorAccessEntriesContext = 0;
12027cd9eafSDmitry Borisov ConfigInfo->HardwareStateSize = 0;
12127cd9eafSDmitry Borisov ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0;
12227cd9eafSDmitry Borisov ConfigInfo->VdmPhysicalVideoMemoryLength = 0;
12327cd9eafSDmitry Borisov
12427cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension,
12527cd9eafSDmitry Borisov L"HardwareInformation.ChipType",
12627cd9eafSDmitry Borisov AdapterChipType,
12727cd9eafSDmitry Borisov sizeof(AdapterChipType));
12827cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension,
12927cd9eafSDmitry Borisov L"HardwareInformation.DacType",
13027cd9eafSDmitry Borisov AdapterDacType,
13127cd9eafSDmitry Borisov sizeof(AdapterDacType));
13227cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension,
13327cd9eafSDmitry Borisov L"HardwareInformation.MemorySize",
13427cd9eafSDmitry Borisov &DeviceExtension->FrameBufferLength,
13527cd9eafSDmitry Borisov sizeof(ULONG));
13627cd9eafSDmitry Borisov VideoPortSetRegistryParameters(DeviceExtension,
13727cd9eafSDmitry Borisov L"HardwareInformation.AdapterString",
13827cd9eafSDmitry Borisov AdapterString,
13927cd9eafSDmitry Borisov sizeof(AdapterString));
14027cd9eafSDmitry Borisov
14127cd9eafSDmitry Borisov return NO_ERROR;
14227cd9eafSDmitry Borisov }
14327cd9eafSDmitry Borisov
1444dc31254SDmitry Borisov static
1455c7ce447SVictor Perevertkin CODE_SEG("PAGE")
14627cd9eafSDmitry Borisov BOOLEAN
14727cd9eafSDmitry Borisov NTAPI
Pc98VidInitialize(_In_ PVOID HwDeviceExtension)14827cd9eafSDmitry Borisov Pc98VidInitialize(
14927cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension)
15027cd9eafSDmitry Borisov {
15127cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
15227cd9eafSDmitry Borisov
15327cd9eafSDmitry Borisov PAGED_CODE();
15427cd9eafSDmitry Borisov
15527cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s()\n", __FUNCTION__));
15627cd9eafSDmitry Borisov
15727cd9eafSDmitry Borisov DeviceExtension->ModeCount = RTL_NUMBER_OF(VideoModes);
15827cd9eafSDmitry Borisov DeviceExtension->MonitorCount = 1;
15927cd9eafSDmitry Borisov
16027cd9eafSDmitry Borisov return TRUE;
16127cd9eafSDmitry Borisov }
16227cd9eafSDmitry Borisov
1634dc31254SDmitry Borisov static
1645c7ce447SVictor Perevertkin CODE_SEG("PAGE")
16527cd9eafSDmitry Borisov VP_STATUS
16627cd9eafSDmitry Borisov NTAPI
Pc98VidGetVideoChildDescriptor(_In_ PVOID HwDeviceExtension,_In_ PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,_Out_ PVIDEO_CHILD_TYPE VideoChildType,_Out_ PUCHAR pChildDescriptor,_Out_ PULONG UId,_Out_ PULONG pUnused)16727cd9eafSDmitry Borisov Pc98VidGetVideoChildDescriptor(
16827cd9eafSDmitry Borisov _In_ PVOID HwDeviceExtension,
16927cd9eafSDmitry Borisov _In_ PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
17027cd9eafSDmitry Borisov _Out_ PVIDEO_CHILD_TYPE VideoChildType,
17127cd9eafSDmitry Borisov _Out_ PUCHAR pChildDescriptor,
17227cd9eafSDmitry Borisov _Out_ PULONG UId,
17327cd9eafSDmitry Borisov _Out_ PULONG pUnused)
17427cd9eafSDmitry Borisov {
17527cd9eafSDmitry Borisov PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
17627cd9eafSDmitry Borisov
17727cd9eafSDmitry Borisov UNREFERENCED_PARAMETER(pChildDescriptor);
17827cd9eafSDmitry Borisov
17927cd9eafSDmitry Borisov PAGED_CODE();
18027cd9eafSDmitry Borisov
18127cd9eafSDmitry Borisov VideoDebugPrint((Trace, "%s() Index %d\n",
18227cd9eafSDmitry Borisov __FUNCTION__, ChildEnumInfo->ChildIndex));
18327cd9eafSDmitry Borisov
18427cd9eafSDmitry Borisov *pUnused = 0;
18527cd9eafSDmitry Borisov
18627cd9eafSDmitry Borisov if (ChildEnumInfo->ChildIndex > 0 &&
18727cd9eafSDmitry Borisov ChildEnumInfo->ChildIndex <= DeviceExtension->MonitorCount)
18827cd9eafSDmitry Borisov {
18927cd9eafSDmitry Borisov *VideoChildType = Monitor;
19027cd9eafSDmitry Borisov *UId = MONITOR_HW_ID;
19127cd9eafSDmitry Borisov
19227cd9eafSDmitry Borisov return VIDEO_ENUM_MORE_DEVICES;
19327cd9eafSDmitry Borisov }
19427cd9eafSDmitry Borisov
19527cd9eafSDmitry Borisov return ERROR_NO_MORE_DEVICES;
19627cd9eafSDmitry Borisov }
19727cd9eafSDmitry Borisov
198*f7d825e6SDmitry Borisov #if defined(_MSC_VER)
199*f7d825e6SDmitry Borisov /*
200*f7d825e6SDmitry Borisov * Avoid C2983 error for MSVC 2015. There is no such thing
201*f7d825e6SDmitry Borisov * as DRIVER_INITIALIZE for video miniport drivers.
202*f7d825e6SDmitry Borisov */
203*f7d825e6SDmitry Borisov #pragma alloc_text(INIT, DriverEntry)
204*f7d825e6SDmitry Borisov #else
205*f7d825e6SDmitry Borisov CODE_SEG("INIT")
206*f7d825e6SDmitry Borisov #endif
20727cd9eafSDmitry Borisov ULONG
20827cd9eafSDmitry Borisov NTAPI
DriverEntry(_In_ PVOID Context1,_In_ PVOID Context2)20927cd9eafSDmitry Borisov DriverEntry(
21027cd9eafSDmitry Borisov _In_ PVOID Context1,
21127cd9eafSDmitry Borisov _In_ PVOID Context2)
21227cd9eafSDmitry Borisov {
21327cd9eafSDmitry Borisov VIDEO_HW_INITIALIZATION_DATA InitData;
21427cd9eafSDmitry Borisov ULONG Status;
21527cd9eafSDmitry Borisov BOOLEAN IsLiveCd;
21627cd9eafSDmitry Borisov
21727cd9eafSDmitry Borisov VideoDebugPrint((Trace, "(%s:%d) %s()\n",
21827cd9eafSDmitry Borisov __FILE__, __LINE__, __FUNCTION__));
21927cd9eafSDmitry Borisov
22027cd9eafSDmitry Borisov // FIXME: Detect IsLiveCd
22127cd9eafSDmitry Borisov IsLiveCd = TRUE;
22227cd9eafSDmitry Borisov
22327cd9eafSDmitry Borisov VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
22427cd9eafSDmitry Borisov InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
22527cd9eafSDmitry Borisov InitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
22627cd9eafSDmitry Borisov InitData.HwFindAdapter = Pc98VidFindAdapter;
22727cd9eafSDmitry Borisov InitData.HwInitialize = Pc98VidInitialize;
22827cd9eafSDmitry Borisov InitData.HwStartIO = Pc98VidStartIO;
22927cd9eafSDmitry Borisov /*
23027cd9eafSDmitry Borisov * On LiveCD, we expect to see the initialized video
23127cd9eafSDmitry Borisov * before starting the device enumeration,
23227cd9eafSDmitry Borisov * so we should mark the driver as non-PnP miniport.
23327cd9eafSDmitry Borisov */
23427cd9eafSDmitry Borisov if (!IsLiveCd)
23527cd9eafSDmitry Borisov {
23627cd9eafSDmitry Borisov InitData.HwGetPowerState = Pc98VidGetPowerState;
23727cd9eafSDmitry Borisov InitData.HwSetPowerState = Pc98VidSetPowerState;
23827cd9eafSDmitry Borisov InitData.HwGetVideoChildDescriptor = Pc98VidGetVideoChildDescriptor;
23927cd9eafSDmitry Borisov }
24027cd9eafSDmitry Borisov
241*f7d825e6SDmitry Borisov InitData.HwLegacyResourceList = (PVIDEO_ACCESS_RANGE)LegacyRangeList;
24227cd9eafSDmitry Borisov InitData.HwLegacyResourceCount = RTL_NUMBER_OF(LegacyRangeList);
24327cd9eafSDmitry Borisov
24427cd9eafSDmitry Borisov InitData.AdapterInterfaceType = Isa;
24527cd9eafSDmitry Borisov
24627cd9eafSDmitry Borisov Status = VideoPortInitialize(Context1, Context2, &InitData, NULL);
24727cd9eafSDmitry Borisov if (!NT_SUCCESS(Status))
24827cd9eafSDmitry Borisov {
24927cd9eafSDmitry Borisov VideoDebugPrint((Error, "(%s:%d) %s() Initialization failed 0x%lX\n",
25027cd9eafSDmitry Borisov __FILE__, __LINE__, __FUNCTION__, Status));
25127cd9eafSDmitry Borisov }
25227cd9eafSDmitry Borisov
25327cd9eafSDmitry Borisov return Status;
25427cd9eafSDmitry Borisov }
255