1 /* 2 * PROJECT: FreeLoader 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Hardware-specific routines for NEC PC-98 series 5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com) 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include <freeldr.h> 11 12 #include <debug.h> 13 DBG_DEFAULT_CHANNEL(HWDETECT); 14 15 /* GLOBALS ********************************************************************/ 16 17 BOOLEAN HiResoMachine; 18 19 /* FUNCTIONS ******************************************************************/ 20 21 VOID 22 Pc98GetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize) 23 { 24 *ExtendedBIOSDataArea = HiResoMachine ? MEM_EXTENDED_HIGH_RESO : MEM_EXTENDED_NORMAL; 25 *ExtendedBIOSDataSize = 64; 26 } 27 28 VOID 29 Pc98HwIdle(VOID) 30 { 31 /* Unimplemented */ 32 } 33 34 VOID 35 Pc98PrepareForReactOS(VOID) 36 { 37 Pc98DiskPrepareForReactOS(); 38 Pc98VideoPrepareForReactOS(); 39 DiskStopFloppyMotor(); 40 DebugDisableScreenPort(); 41 } 42 43 ULONG 44 Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber) 45 { 46 PPC98_DISK_DRIVE DiskDrive; 47 48 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber); 49 if (!DiskDrive) 50 { 51 ERR("Failed to get drive 0x%x\n", DriveNumber); 52 return 0x1FC00; 53 } 54 55 if (((DiskDrive->DaUa & 0xF0) == 0x30) || 56 ((DiskDrive->DaUa & 0xF0) == 0xB0)) 57 { 58 /* 1.44 MB floppy */ 59 return 0x1FE00; 60 } 61 else if (DiskDrive->Type & DRIVE_FDD) 62 { 63 return 0x1FC00; 64 } 65 66 return 0x1F800; 67 } 68 69 VOID __cdecl ChainLoadBiosBootSectorCode( 70 IN UCHAR BootDrive OPTIONAL, 71 IN ULONG BootPartition OPTIONAL) 72 { 73 REGS Regs; 74 PPC98_DISK_DRIVE DiskDrive; 75 USHORT LoadAddress; 76 UCHAR DriveNumber = BootDrive ? BootDrive : FrldrBootDrive; 77 78 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber); 79 if (!DiskDrive) 80 { 81 ERR("Failed to get drive 0x%x\n", DriveNumber); 82 return; 83 } 84 85 LoadAddress = (USHORT)(Pc98GetBootSectorLoadAddress(DriveNumber) >> 4); 86 87 RtlZeroMemory(&Regs, sizeof(Regs)); 88 Regs.w.ax = DiskDrive->DaUa; 89 Regs.w.si = LoadAddress; 90 Regs.w.es = LoadAddress; 91 *(PUCHAR)MEM_DISK_BOOT = DiskDrive->DaUa; 92 93 Pc98VideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK)); 94 95 Relocator16Boot(&Regs, 96 /* Stack segment:pointer */ 97 0x0020, 0x00FF, 98 /* Code segment:pointer */ 99 LoadAddress, 0x0000); 100 } 101 102 static BOOLEAN 103 Pc98ArchTest(VOID) 104 { 105 REGS RegsIn, RegsOut; 106 107 /* Int 1Ah AX=1000h 108 * NEC PC-9800 series - Installation check 109 */ 110 RegsIn.w.ax = 0x1000; 111 Int386(0x1A, &RegsIn, &RegsOut); 112 113 return RegsOut.w.ax != 0x1000; 114 } 115 116 VOID 117 MachInit(const char *CmdLine) 118 { 119 if (!Pc98ArchTest()) 120 { 121 ERR("This is not a supported PC98!\n"); 122 123 /* Disable and halt the CPU */ 124 _disable(); 125 __halt(); 126 127 while (TRUE) 128 NOTHING; 129 } 130 131 /* Setup vtbl */ 132 RtlZeroMemory(&MachVtbl, sizeof(MachVtbl)); 133 MachVtbl.ConsPutChar = Pc98ConsPutChar; 134 MachVtbl.ConsKbHit = Pc98ConsKbHit; 135 MachVtbl.ConsGetCh = Pc98ConsGetCh; 136 MachVtbl.VideoClearScreen = Pc98VideoClearScreen; 137 MachVtbl.VideoSetDisplayMode = Pc98VideoSetDisplayMode; 138 MachVtbl.VideoGetDisplaySize = Pc98VideoGetDisplaySize; 139 MachVtbl.VideoGetBufferSize = Pc98VideoGetBufferSize; 140 MachVtbl.VideoGetFontsFromFirmware = Pc98VideoGetFontsFromFirmware; 141 MachVtbl.VideoSetTextCursorPosition = Pc98VideoSetTextCursorPosition; 142 MachVtbl.VideoHideShowTextCursor = Pc98VideoHideShowTextCursor; 143 MachVtbl.VideoPutChar = Pc98VideoPutChar; 144 MachVtbl.VideoCopyOffScreenBufferToVRAM = Pc98VideoCopyOffScreenBufferToVRAM; 145 MachVtbl.VideoIsPaletteFixed = Pc98VideoIsPaletteFixed; 146 MachVtbl.VideoSetPaletteColor = Pc98VideoSetPaletteColor; 147 MachVtbl.VideoGetPaletteColor = Pc98VideoGetPaletteColor; 148 MachVtbl.VideoSync = Pc98VideoSync; 149 MachVtbl.Beep = Pc98Beep; 150 MachVtbl.PrepareForReactOS = Pc98PrepareForReactOS; 151 MachVtbl.GetMemoryMap = Pc98MemGetMemoryMap; 152 MachVtbl.GetExtendedBIOSData = Pc98GetExtendedBIOSData; 153 MachVtbl.GetFloppyCount = Pc98GetFloppyCount; 154 MachVtbl.DiskReadLogicalSectors = Pc98DiskReadLogicalSectors; 155 MachVtbl.DiskGetDriveGeometry = Pc98DiskGetDriveGeometry; 156 MachVtbl.DiskGetCacheableBlockCount = Pc98DiskGetCacheableBlockCount; 157 MachVtbl.GetTime = Pc98GetTime; 158 MachVtbl.InitializeBootDevices = Pc98InitializeBootDevices; 159 MachVtbl.HwDetect = Pc98HwDetect; 160 MachVtbl.HwIdle = Pc98HwIdle; 161 162 HiResoMachine = *(PUCHAR)MEM_BIOS_FLAG1 & HIGH_RESOLUTION_FLAG; 163 164 HalpCalibrateStallExecution(); 165 Pc98VideoInit(); 166 } 167