1 /* 2 * PROJECT: ReactOS framebuffer driver for NEC PC-98 series 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Miniport driver entrypoint 5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com) 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "pc98vid.h" 11 12 /* GLOBALS ********************************************************************/ 13 14 DATA_SEG("PAGECONS") 15 const VIDEOMODE VideoModes[] = 16 { 17 {640, 480, GRAPH_HF_31KHZ, GDC2_CLOCK1_5MHZ, GDC2_CLOCK2_5MHZ, 18 GDC2_MODE_LINES_800, 60, 19 {0, 80, 12, 2, 4, 4, 6, 480, 37}, {0, 80, 12, 2, 4, 132, 6, 480, 37}} 20 }; 21 22 DATA_SEG("PAGECONS") 23 const VIDEO_ACCESS_RANGE LegacyRangeList[] = 24 { 25 { {{0x60, 0}}, 0x00000001, 1, 1, 1, 0 }, 26 { {{0x62, 0}}, 0x00000001, 1, 1, 1, 0 }, 27 { {{0x68, 0}}, 0x00000001, 1, 1, 1, 0 }, 28 { {{0x6A, 0}}, 0x00000001, 1, 1, 1, 0 }, 29 { {{0x7C, 0}}, 0x00000001, 1, 1, 1, 0 }, 30 { {{0xA0, 0}}, 0x00000001, 1, 1, 1, 0 }, 31 { {{0xA2, 0}}, 0x00000001, 1, 1, 1, 0 }, 32 { {{0xA4, 0}}, 0x00000001, 1, 1, 1, 0 }, 33 { {{0xA6, 0}}, 0x00000001, 1, 1, 1, 0 }, 34 { {{0xA8, 0}}, 0x00000001, 1, 1, 1, 0 }, 35 { {{0xAA, 0}}, 0x00000001, 1, 1, 1, 0 }, 36 { {{0xAC, 0}}, 0x00000001, 1, 1, 1, 0 }, 37 { {{0xAE, 0}}, 0x00000001, 1, 1, 1, 0 }, 38 { {{0x9A0, 0}}, 0x00000001, 1, 1, 1, 0 }, 39 { {{0x9A2, 0}}, 0x00000001, 1, 1, 1, 0 }, 40 { {{0x9A8, 0}}, 0x00000001, 1, 1, 1, 0 }, 41 { {{0xFAC, 0}}, 0x00000001, 1, 1, 1, 0 }, 42 { {{VRAM_NORMAL_PLANE_I, 0}}, PEGC_CONTROL_SIZE, 0, 0, 1, 0 }, 43 { {{PEGC_FRAMEBUFFER_PACKED, 0}}, PEGC_FRAMEBUFFER_SIZE, 0, 0, 1, 0 } 44 }; 45 #define CONTROL_RANGE_INDEX 17 46 #define FRAMEBUFFER_RANGE_INDEX 18 47 48 /* FUNCTIONS ******************************************************************/ 49 50 static 51 CODE_SEG("PAGE") 52 VP_STATUS 53 NTAPI 54 Pc98VidFindAdapter( 55 _In_ PVOID HwDeviceExtension, 56 _In_opt_ PVOID HwContext, 57 _In_opt_ PWSTR ArgumentString, 58 _Inout_ PVIDEO_PORT_CONFIG_INFO ConfigInfo, 59 _Out_ PUCHAR Again) 60 { 61 VP_STATUS Status; 62 PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 63 ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; 64 static WCHAR AdapterChipType[] = L"Onboard"; 65 static WCHAR AdapterDacType[] = L"8 bit"; 66 static WCHAR AdapterString[] = L"PEGC"; 67 68 PAGED_CODE(); 69 70 VideoDebugPrint((Trace, "%s()\n", __FUNCTION__)); 71 72 if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) 73 return ERROR_INVALID_PARAMETER; 74 75 Status = VideoPortVerifyAccessRanges(DeviceExtension, 76 RTL_NUMBER_OF(LegacyRangeList), 77 (PVIDEO_ACCESS_RANGE)LegacyRangeList); 78 if (Status != NO_ERROR) 79 { 80 VideoDebugPrint((Error, "%s() Resource conflict was found\n", __FUNCTION__)); 81 82 return ERROR_INVALID_PARAMETER; 83 } 84 85 DeviceExtension->PegcControl = LegacyRangeList[CONTROL_RANGE_INDEX].RangeStart; 86 DeviceExtension->PegcControlLength = LegacyRangeList[CONTROL_RANGE_INDEX].RangeLength; 87 DeviceExtension->FrameBuffer = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeStart; 88 DeviceExtension->FrameBufferLength = LegacyRangeList[FRAMEBUFFER_RANGE_INDEX].RangeLength; 89 90 Status = VideoPortMapMemory(DeviceExtension, 91 DeviceExtension->PegcControl, 92 &DeviceExtension->PegcControlLength, 93 &inIoSpace, 94 (PVOID)&DeviceExtension->PegcControlVa); 95 if (Status != NO_ERROR) 96 { 97 VideoDebugPrint((Error, "%s() Failed to map control memory\n", __FUNCTION__)); 98 99 VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL); 100 101 return ERROR_DEV_NOT_EXIST; 102 } 103 104 if (!HasPegcController(DeviceExtension)) 105 { 106 VideoDebugPrint((Error, "%s() Unsupported hardware\n", __FUNCTION__)); 107 108 VideoPortVerifyAccessRanges(DeviceExtension, 0, NULL); 109 VideoPortUnmapMemory(DeviceExtension, 110 (PVOID)DeviceExtension->PegcControlVa, 111 NULL); 112 113 return ERROR_DEV_NOT_EXIST; 114 } 115 116 /* Not VGA-compatible */ 117 ConfigInfo->NumEmulatorAccessEntries = 0; 118 ConfigInfo->EmulatorAccessEntries = NULL; 119 ConfigInfo->EmulatorAccessEntriesContext = 0; 120 ConfigInfo->HardwareStateSize = 0; 121 ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0; 122 ConfigInfo->VdmPhysicalVideoMemoryLength = 0; 123 124 VideoPortSetRegistryParameters(DeviceExtension, 125 L"HardwareInformation.ChipType", 126 AdapterChipType, 127 sizeof(AdapterChipType)); 128 VideoPortSetRegistryParameters(DeviceExtension, 129 L"HardwareInformation.DacType", 130 AdapterDacType, 131 sizeof(AdapterDacType)); 132 VideoPortSetRegistryParameters(DeviceExtension, 133 L"HardwareInformation.MemorySize", 134 &DeviceExtension->FrameBufferLength, 135 sizeof(ULONG)); 136 VideoPortSetRegistryParameters(DeviceExtension, 137 L"HardwareInformation.AdapterString", 138 AdapterString, 139 sizeof(AdapterString)); 140 141 return NO_ERROR; 142 } 143 144 static 145 CODE_SEG("PAGE") 146 BOOLEAN 147 NTAPI 148 Pc98VidInitialize( 149 _In_ PVOID HwDeviceExtension) 150 { 151 PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 152 153 PAGED_CODE(); 154 155 VideoDebugPrint((Trace, "%s()\n", __FUNCTION__)); 156 157 DeviceExtension->ModeCount = RTL_NUMBER_OF(VideoModes); 158 DeviceExtension->MonitorCount = 1; 159 160 return TRUE; 161 } 162 163 static 164 CODE_SEG("PAGE") 165 VP_STATUS 166 NTAPI 167 Pc98VidGetVideoChildDescriptor( 168 _In_ PVOID HwDeviceExtension, 169 _In_ PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, 170 _Out_ PVIDEO_CHILD_TYPE VideoChildType, 171 _Out_ PUCHAR pChildDescriptor, 172 _Out_ PULONG UId, 173 _Out_ PULONG pUnused) 174 { 175 PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; 176 177 UNREFERENCED_PARAMETER(pChildDescriptor); 178 179 PAGED_CODE(); 180 181 VideoDebugPrint((Trace, "%s() Index %d\n", 182 __FUNCTION__, ChildEnumInfo->ChildIndex)); 183 184 *pUnused = 0; 185 186 if (ChildEnumInfo->ChildIndex > 0 && 187 ChildEnumInfo->ChildIndex <= DeviceExtension->MonitorCount) 188 { 189 *VideoChildType = Monitor; 190 *UId = MONITOR_HW_ID; 191 192 return VIDEO_ENUM_MORE_DEVICES; 193 } 194 195 return ERROR_NO_MORE_DEVICES; 196 } 197 198 #if defined(_MSC_VER) 199 /* 200 * Avoid C2983 error for MSVC 2015. There is no such thing 201 * as DRIVER_INITIALIZE for video miniport drivers. 202 */ 203 #pragma alloc_text(INIT, DriverEntry) 204 #else 205 CODE_SEG("INIT") 206 #endif 207 ULONG 208 NTAPI 209 DriverEntry( 210 _In_ PVOID Context1, 211 _In_ PVOID Context2) 212 { 213 VIDEO_HW_INITIALIZATION_DATA InitData; 214 ULONG Status; 215 BOOLEAN IsLiveCd; 216 217 VideoDebugPrint((Trace, "(%s:%d) %s()\n", 218 __FILE__, __LINE__, __FUNCTION__)); 219 220 // FIXME: Detect IsLiveCd 221 IsLiveCd = TRUE; 222 223 VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); 224 InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); 225 InitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 226 InitData.HwFindAdapter = Pc98VidFindAdapter; 227 InitData.HwInitialize = Pc98VidInitialize; 228 InitData.HwStartIO = Pc98VidStartIO; 229 /* 230 * On LiveCD, we expect to see the initialized video 231 * before starting the device enumeration, 232 * so we should mark the driver as non-PnP miniport. 233 */ 234 if (!IsLiveCd) 235 { 236 InitData.HwGetPowerState = Pc98VidGetPowerState; 237 InitData.HwSetPowerState = Pc98VidSetPowerState; 238 InitData.HwGetVideoChildDescriptor = Pc98VidGetVideoChildDescriptor; 239 } 240 241 InitData.HwLegacyResourceList = (PVIDEO_ACCESS_RANGE)LegacyRangeList; 242 InitData.HwLegacyResourceCount = RTL_NUMBER_OF(LegacyRangeList); 243 244 InitData.AdapterInterfaceType = Isa; 245 246 Status = VideoPortInitialize(Context1, Context2, &InitData, NULL); 247 if (!NT_SUCCESS(Status)) 248 { 249 VideoDebugPrint((Error, "(%s:%d) %s() Initialization failed 0x%lX\n", 250 __FILE__, __LINE__, __FUNCTION__, Status)); 251 } 252 253 return Status; 254 } 255