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