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