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 _disable(); 122 __halt(); 123 124 while (TRUE) 125 NOTHING; 126 } 127 128 /* Setup vtbl */ 129 RtlZeroMemory(&MachVtbl, sizeof(MACHVTBL)); 130 MachVtbl.ConsPutChar = Pc98ConsPutChar; 131 MachVtbl.ConsKbHit = Pc98ConsKbHit; 132 MachVtbl.ConsGetCh = Pc98ConsGetCh; 133 MachVtbl.VideoClearScreen = Pc98VideoClearScreen; 134 MachVtbl.VideoSetDisplayMode = Pc98VideoSetDisplayMode; 135 MachVtbl.VideoGetDisplaySize = Pc98VideoGetDisplaySize; 136 MachVtbl.VideoGetBufferSize = Pc98VideoGetBufferSize; 137 MachVtbl.VideoGetFontsFromFirmware = Pc98VideoGetFontsFromFirmware; 138 MachVtbl.VideoSetTextCursorPosition = Pc98VideoSetTextCursorPosition; 139 MachVtbl.VideoHideShowTextCursor = Pc98VideoHideShowTextCursor; 140 MachVtbl.VideoPutChar = Pc98VideoPutChar; 141 MachVtbl.VideoCopyOffScreenBufferToVRAM = Pc98VideoCopyOffScreenBufferToVRAM; 142 MachVtbl.VideoIsPaletteFixed = Pc98VideoIsPaletteFixed; 143 MachVtbl.VideoSetPaletteColor = Pc98VideoSetPaletteColor; 144 MachVtbl.VideoGetPaletteColor = Pc98VideoGetPaletteColor; 145 MachVtbl.VideoSync = Pc98VideoSync; 146 MachVtbl.Beep = Pc98Beep; 147 MachVtbl.PrepareForReactOS = Pc98PrepareForReactOS; 148 MachVtbl.GetMemoryMap = Pc98MemGetMemoryMap; 149 MachVtbl.GetExtendedBIOSData = Pc98GetExtendedBIOSData; 150 MachVtbl.GetFloppyCount = Pc98GetFloppyCount; 151 MachVtbl.DiskReadLogicalSectors = Pc98DiskReadLogicalSectors; 152 MachVtbl.DiskGetDriveGeometry = Pc98DiskGetDriveGeometry; 153 MachVtbl.DiskGetCacheableBlockCount = Pc98DiskGetCacheableBlockCount; 154 MachVtbl.GetTime = Pc98GetTime; 155 MachVtbl.InitializeBootDevices = Pc98InitializeBootDevices; 156 MachVtbl.HwDetect = Pc98HwDetect; 157 MachVtbl.HwIdle = Pc98HwIdle; 158 159 HiResoMachine = *(PUCHAR)MEM_BIOS_FLAG1 & HIGH_RESOLUTION_FLAG; 160 161 HalpCalibrateStallExecution(); 162 Pc98VideoInit(); 163 } 164