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: Hardware support code 5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com) 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "pc98vid.h" 11 12 /* GLOBALS ********************************************************************/ 13 14 #define PEGC_MAX_COLORS 256 15 16 /* FUNCTIONS ******************************************************************/ 17 18 static BOOLEAN 19 GraphGetStatus( 20 _In_ UCHAR Status) 21 { 22 UCHAR Result; 23 24 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_STATUS_SELECT, Status); 25 Result = VideoPortReadPortUchar((PUCHAR)GRAPH_IO_i_STATUS); 26 27 return (Result & GRAPH_STATUS_SET) && (Result != 0xFF); 28 } 29 30 static BOOLEAN 31 TestMmio( 32 _In_ PHW_DEVICE_EXTENSION DeviceExtension) 33 { 34 USHORT OldValue, NewValue; 35 36 OldValue = VideoPortReadRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 37 PEGC_MMIO_MODE)); 38 39 /* Bits [15:1] are not writable */ 40 VideoPortWriteRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 41 PEGC_MMIO_MODE), 0x80); 42 NewValue = VideoPortReadRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 43 PEGC_MMIO_MODE)); 44 45 VideoPortWriteRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 46 PEGC_MMIO_MODE), OldValue); 47 48 return !(NewValue & 0x80); 49 } 50 51 static VOID 52 TextSync(VOID) 53 { 54 while (VideoPortReadPortUchar((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC) 55 NOTHING; 56 57 while (!(VideoPortReadPortUchar((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC)) 58 NOTHING; 59 } 60 61 BOOLEAN 62 NTAPI 63 HasPegcController( 64 _In_ PHW_DEVICE_EXTENSION DeviceExtension) 65 { 66 BOOLEAN Success; 67 68 if (GraphGetStatus(GRAPH_STATUS_PEGC)) 69 return TestMmio(DeviceExtension); 70 71 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT); 72 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE); 73 Success = GraphGetStatus(GRAPH_STATUS_PEGC) ? TestMmio(DeviceExtension) : FALSE; 74 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_DISABLE); 75 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT); 76 77 return Success; 78 } 79 80 CODE_SEG("PAGE") 81 VP_STATUS 82 FASTCALL 83 Pc98VidSetCurrentMode( 84 _In_ PHW_DEVICE_EXTENSION DeviceExtension, 85 _In_ PVIDEO_MODE RequestedMode) 86 { 87 SYNCPARAM SyncParameters; 88 CSRFORMPARAM CursorParameters; 89 CSRWPARAM CursorPosition; 90 PITCHPARAM PitchParameters; 91 PRAMPARAM RamParameters; 92 ZOOMPARAM ZoomParameters; 93 UCHAR RelayState; 94 95 PAGED_CODE(); 96 97 VideoDebugPrint((Trace, "%s() Mode %d\n", 98 __FUNCTION__, RequestedMode->RequestedMode)); 99 100 if (RequestedMode->RequestedMode > DeviceExtension->ModeCount) 101 return ERROR_INVALID_PARAMETER; 102 103 /* Blank screen */ 104 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_DISPLAY_DISABLE); 105 106 /* RESET, without FIFO check */ 107 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_COMMAND, GDC_COMMAND_RESET1); 108 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_COMMAND, GDC_COMMAND_RESET1); 109 110 /* Configure chipset */ 111 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_COLORED); 112 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GDC2_MODE_ODD_RLINE_SHOW); 113 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_COLORS_16); 114 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_GRCG); 115 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LCD); 116 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LINES_400); 117 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, 118 VideoModes[RequestedMode->RequestedMode].Clock1); 119 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, 120 VideoModes[RequestedMode->RequestedMode].Clock2); 121 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_HORIZONTAL_SCAN_RATE, 122 VideoModes[RequestedMode->RequestedMode].HorizontalScanRate); 123 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_VIDEO_PAGE, 0); 124 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_VIDEO_PAGE_ACCESS, 0); 125 126 /* =========================== MASTER ============================ */ 127 128 /* MASTER */ 129 WRITE_GDC1_COMMAND(GDC_COMMAND_MASTER); 130 131 /* SYNC */ 132 SyncParameters = VideoModes[RequestedMode->RequestedMode].TextSyncParameters; 133 SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS_AND_CHARACTERS | SYNC_VIDEO_FRAMING_NONINTERLACED | 134 SYNC_DRAW_ONLY_DURING_RETRACE_BLANKING | SYNC_STATIC_RAM_NO_REFRESH; 135 WRITE_GDC1_COMMAND(GDC_COMMAND_SYNC_ON); 136 WRITE_GDC_SYNC((PUCHAR)GDC1_IO_o_PARAM, &SyncParameters); 137 138 /* CSRFORM */ 139 CursorParameters.Show = FALSE; 140 CursorParameters.Blink = FALSE; 141 CursorParameters.BlinkRate = 12; 142 CursorParameters.LinesPerRow = 16; 143 CursorParameters.StartScanLine = 0; 144 CursorParameters.EndScanLine = 15; 145 WRITE_GDC1_COMMAND(GDC_COMMAND_CSRFORM); 146 WRITE_GDC_CSRFORM((PUCHAR)GDC1_IO_o_PARAM, &CursorParameters); 147 148 /* PITCH */ 149 PitchParameters.WordsPerScanline = 80; 150 WRITE_GDC1_COMMAND(GDC_COMMAND_PITCH); 151 WRITE_GDC_PITCH((PUCHAR)GDC1_IO_o_PARAM, &PitchParameters); 152 153 /* PRAM */ 154 RamParameters.StartingAddress = 0; 155 RamParameters.Length = 1023; 156 RamParameters.ImageBit = FALSE; 157 RamParameters.WideDisplay = FALSE; 158 WRITE_GDC1_COMMAND(GDC_COMMAND_PRAM); 159 WRITE_GDC_PRAM((PUCHAR)GDC1_IO_o_PARAM, &RamParameters); 160 161 /* ZOOM */ 162 ZoomParameters.DisplayZoomFactor = 0; 163 ZoomParameters.WritingZoomFactor = 0; 164 WRITE_GDC1_COMMAND(GDC_COMMAND_ZOOM); 165 WRITE_GDC_ZOOM((PUCHAR)GDC1_IO_o_PARAM, &ZoomParameters); 166 167 /* CSRW */ 168 CursorPosition.CursorAddress = 0; 169 CursorPosition.DotAddress = 0; 170 WRITE_GDC1_COMMAND(GDC_COMMAND_CSRW); 171 WRITE_GDC_CSRW((PUCHAR)GDC1_IO_o_PARAM, &CursorPosition); 172 173 /* START */ 174 WRITE_GDC1_COMMAND(GDC_COMMAND_BCTRL_START); 175 176 /* ============================ SLAVE ============================ */ 177 178 /* SLAVE */ 179 WRITE_GDC2_COMMAND(GDC_COMMAND_SLAVE); 180 181 /* SYNC */ 182 SyncParameters = VideoModes[RequestedMode->RequestedMode].VideoSyncParameters; 183 SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS | SYNC_VIDEO_FRAMING_NONINTERLACED | 184 SYNC_DRAW_DURING_ACTIVE_DISPLAY_TIME_AND_RETRACE_BLANKING | 185 SYNC_STATIC_RAM_NO_REFRESH; 186 WRITE_GDC2_COMMAND(GDC_COMMAND_SYNC_ON); 187 WRITE_GDC_SYNC((PUCHAR)GDC2_IO_o_PARAM, &SyncParameters); 188 189 /* CSRFORM */ 190 CursorParameters.Show = FALSE; 191 CursorParameters.Blink = FALSE; 192 CursorParameters.BlinkRate = 0; 193 CursorParameters.LinesPerRow = 1; 194 CursorParameters.StartScanLine = 0; 195 CursorParameters.EndScanLine = 0; 196 WRITE_GDC2_COMMAND(GDC_COMMAND_CSRFORM); 197 WRITE_GDC_CSRFORM((PUCHAR)GDC2_IO_o_PARAM, &CursorParameters); 198 199 /* PITCH */ 200 PitchParameters.WordsPerScanline = 80; 201 WRITE_GDC2_COMMAND(GDC_COMMAND_PITCH); 202 WRITE_GDC_PITCH((PUCHAR)GDC2_IO_o_PARAM, &PitchParameters); 203 204 /* PRAM */ 205 RamParameters.StartingAddress = 0; 206 RamParameters.Length = 1023; 207 RamParameters.ImageBit = TRUE; 208 RamParameters.WideDisplay = FALSE; 209 WRITE_GDC2_COMMAND(GDC_COMMAND_PRAM); 210 WRITE_GDC_PRAM((PUCHAR)GDC2_IO_o_PARAM, &RamParameters); 211 212 /* ZOOM */ 213 ZoomParameters.DisplayZoomFactor = 0; 214 ZoomParameters.WritingZoomFactor = 0; 215 WRITE_GDC2_COMMAND(GDC_COMMAND_ZOOM); 216 WRITE_GDC_ZOOM((PUCHAR)GDC2_IO_o_PARAM, &ZoomParameters); 217 218 /* CSRW */ 219 CursorPosition.CursorAddress = 0; 220 CursorPosition.DotAddress = 0; 221 WRITE_GDC2_COMMAND(GDC_COMMAND_CSRW); 222 WRITE_GDC_CSRW((PUCHAR)GDC2_IO_o_PARAM, &CursorPosition); 223 224 /* Synchronize the master sync source */ 225 TextSync(); 226 TextSync(); 227 TextSync(); 228 TextSync(); 229 230 /* START */ 231 WRITE_GDC2_COMMAND(GDC_COMMAND_BCTRL_START); 232 233 /* 256 colors, packed pixel */ 234 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT); 235 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE); 236 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, 237 VideoModes[RequestedMode->RequestedMode].Mem); 238 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT); 239 VideoPortWriteRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 240 PEGC_MMIO_MODE), PEGC_MODE_PACKED); 241 VideoPortWriteRegisterUshort((PUSHORT)(DeviceExtension->PegcControlVa + 242 PEGC_MMIO_FRAMEBUFFER), PEGC_FB_MAP); 243 244 /* Select the video source */ 245 RelayState = VideoPortReadPortUchar((PUCHAR)GRAPH_IO_i_RELAY) & 246 ~(GRAPH_RELAY_0 | GRAPH_RELAY_1); 247 RelayState |= GRAPH_VID_SRC_INTERNAL | GRAPH_SRC_GDC; 248 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_RELAY, RelayState); 249 250 /* Unblank screen */ 251 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_DISPLAY_ENABLE); 252 253 DeviceExtension->CurrentMode = RequestedMode->RequestedMode; 254 255 return NO_ERROR; 256 } 257 258 CODE_SEG("PAGE") 259 VP_STATUS 260 FASTCALL 261 Pc98VidSetColorRegisters( 262 _In_ PVIDEO_CLUT ColorLookUpTable) 263 { 264 USHORT Entry; 265 266 PAGED_CODE(); 267 268 VideoDebugPrint((Trace, "%s()\n", __FUNCTION__)); 269 270 if (ColorLookUpTable->NumEntries > PEGC_MAX_COLORS) 271 return ERROR_INVALID_PARAMETER; 272 273 for (Entry = ColorLookUpTable->FirstEntry; 274 Entry < ColorLookUpTable->FirstEntry + ColorLookUpTable->NumEntries; 275 ++Entry) 276 { 277 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_PALETTE_INDEX, Entry); 278 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_RED, 279 ColorLookUpTable->LookupTable[Entry].RgbArray.Red); 280 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_GREEN, 281 ColorLookUpTable->LookupTable[Entry].RgbArray.Green); 282 VideoPortWritePortUchar((PUCHAR)GDC2_IO_o_BLUE, 283 ColorLookUpTable->LookupTable[Entry].RgbArray.Blue); 284 } 285 286 return NO_ERROR; 287 } 288 289 CODE_SEG("PAGE") 290 VP_STATUS 291 NTAPI 292 Pc98VidGetPowerState( 293 _In_ PVOID HwDeviceExtension, 294 _In_ ULONG HwId, 295 _In_ PVIDEO_POWER_MANAGEMENT VideoPowerControl) 296 { 297 PAGED_CODE(); 298 299 VideoDebugPrint((Trace, "%s() Id %lX, State %x\n", 300 __FUNCTION__, HwId, VideoPowerControl->PowerState)); 301 302 if (HwId == MONITOR_HW_ID || HwId == DISPLAY_ADAPTER_HW_ID) 303 { 304 switch (VideoPowerControl->PowerState) 305 { 306 case VideoPowerOn: 307 case VideoPowerStandBy: 308 case VideoPowerSuspend: 309 case VideoPowerOff: 310 case VideoPowerShutdown: 311 return NO_ERROR; 312 } 313 } 314 315 return ERROR_DEVICE_REINITIALIZATION_NEEDED; 316 } 317 318 CODE_SEG("PAGE") 319 VP_STATUS 320 NTAPI 321 Pc98VidSetPowerState( 322 _In_ PVOID HwDeviceExtension, 323 _In_ ULONG HwId, 324 _In_ PVIDEO_POWER_MANAGEMENT VideoPowerControl) 325 { 326 UCHAR Dpms; 327 328 PAGED_CODE(); 329 330 VideoDebugPrint((Trace, "%s() Id %lX, State %x\n", 331 __FUNCTION__, HwId, VideoPowerControl->PowerState)); 332 333 if (HwId == MONITOR_HW_ID) 334 { 335 Dpms = VideoPortReadPortUchar((PUCHAR)GRAPH_IO_i_DPMS); 336 337 switch (VideoPowerControl->PowerState) 338 { 339 case VideoPowerOn: 340 /* Turn on HS/VS signals */ 341 Dpms &= ~(GRAPH_DPMS_HSYNC_MASK | GRAPH_DPMS_VSYNC_MASK); 342 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_DPMS, Dpms); 343 344 /* Unblank screen */ 345 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 346 GRAPH_MODE_DISPLAY_ENABLE); 347 break; 348 349 case VideoPowerStandBy: 350 /* Disable HS signal */ 351 Dpms = (Dpms | GRAPH_DPMS_HSYNC_MASK) & ~GRAPH_DPMS_VSYNC_MASK; 352 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_DPMS, Dpms); 353 break; 354 355 case VideoPowerSuspend: 356 /* Disable VS signal */ 357 Dpms = (Dpms | GRAPH_DPMS_VSYNC_MASK) & ~GRAPH_DPMS_HSYNC_MASK; 358 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_DPMS, Dpms); 359 break; 360 361 case VideoPowerOff: 362 case VideoPowerShutdown: 363 /* Turn off HS/VS signals */ 364 Dpms |= GRAPH_DPMS_HSYNC_MASK | GRAPH_DPMS_VSYNC_MASK; 365 VideoPortWritePortUchar((PUCHAR)GRAPH_IO_o_DPMS, Dpms); 366 367 /* Blank screen */ 368 VideoPortWritePortUchar((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 369 GRAPH_MODE_DISPLAY_DISABLE); 370 break; 371 } 372 } 373 374 return NO_ERROR; 375 } 376