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 } 41 42 ULONG 43 Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber) 44 { 45 PPC98_DISK_DRIVE DiskDrive; 46 47 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber); 48 if (!DiskDrive) 49 { 50 ERR("Failed to get drive 0x%x\n", DriveNumber); 51 return 0x1FC00; 52 } 53 54 if (((DiskDrive->DaUa & 0xF0) == 0x30) || 55 ((DiskDrive->DaUa & 0xF0) == 0xB0)) 56 { 57 /* 1.44 MB floppy */ 58 return 0x1FE00; 59 } 60 else if (DiskDrive->Type & DRIVE_FDD) 61 { 62 return 0x1FC00; 63 } 64 65 return 0x1F800; 66 } 67 68 VOID __cdecl ChainLoadBiosBootSectorCode( 69 IN UCHAR BootDrive OPTIONAL, 70 IN ULONG BootPartition OPTIONAL) 71 { 72 REGS Regs; 73 PPC98_DISK_DRIVE DiskDrive; 74 USHORT LoadAddress; 75 UCHAR DriveNumber = BootDrive ? BootDrive : FrldrBootDrive; 76 77 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber); 78 if (!DiskDrive) 79 { 80 ERR("Failed to get drive 0x%x\n", DriveNumber); 81 return; 82 } 83 84 LoadAddress = (USHORT)(Pc98GetBootSectorLoadAddress(DriveNumber) >> 4); 85 86 RtlZeroMemory(&Regs, sizeof(Regs)); 87 Regs.w.ax = DiskDrive->DaUa; 88 Regs.w.si = LoadAddress; 89 Regs.w.es = LoadAddress; 90 *(PUCHAR)MEM_DISK_BOOT = DiskDrive->DaUa; 91 92 Pc98VideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK)); 93 94 Relocator16Boot(&Regs, 95 /* Stack segment:pointer */ 96 0x0020, 0x00FF, 97 /* Code segment:pointer */ 98 LoadAddress, 0x0000); 99 } 100 101 static BOOLEAN 102 Pc98ArchTest(VOID) 103 { 104 REGS RegsIn, RegsOut; 105 106 /* Int 1Ah AX=1000h 107 * NEC PC-9800 series - Installation check 108 */ 109 RegsIn.w.ax = 0x1000; 110 Int386(0x1A, &RegsIn, &RegsOut); 111 112 return RegsOut.w.ax != 0x1000; 113 } 114 115 VOID 116 MachInit(const char *CmdLine) 117 { 118 if (!Pc98ArchTest()) 119 { 120 _disable(); 121 __halt(); 122 123 while (TRUE) 124 NOTHING; 125 } 126 127 /* Setup vtbl */ 128 RtlZeroMemory(&MachVtbl, sizeof(MACHVTBL)); 129 MachVtbl.ConsPutChar = Pc98ConsPutChar; 130 MachVtbl.ConsKbHit = Pc98ConsKbHit; 131 MachVtbl.ConsGetCh = Pc98ConsGetCh; 132 MachVtbl.VideoClearScreen = Pc98VideoClearScreen; 133 MachVtbl.VideoSetDisplayMode = Pc98VideoSetDisplayMode; 134 MachVtbl.VideoGetDisplaySize = Pc98VideoGetDisplaySize; 135 MachVtbl.VideoGetBufferSize = Pc98VideoGetBufferSize; 136 MachVtbl.VideoGetFontsFromFirmware = Pc98VideoGetFontsFromFirmware; 137 MachVtbl.VideoSetTextCursorPosition = Pc98VideoSetTextCursorPosition; 138 MachVtbl.VideoHideShowTextCursor = Pc98VideoHideShowTextCursor; 139 MachVtbl.VideoPutChar = Pc98VideoPutChar; 140 MachVtbl.VideoCopyOffScreenBufferToVRAM = Pc98VideoCopyOffScreenBufferToVRAM; 141 MachVtbl.VideoIsPaletteFixed = Pc98VideoIsPaletteFixed; 142 MachVtbl.VideoSetPaletteColor = Pc98VideoSetPaletteColor; 143 MachVtbl.VideoGetPaletteColor = Pc98VideoGetPaletteColor; 144 MachVtbl.VideoSync = Pc98VideoSync; 145 MachVtbl.Beep = Pc98Beep; 146 MachVtbl.PrepareForReactOS = Pc98PrepareForReactOS; 147 MachVtbl.GetMemoryMap = Pc98MemGetMemoryMap; 148 MachVtbl.GetExtendedBIOSData = Pc98GetExtendedBIOSData; 149 MachVtbl.GetFloppyCount = Pc98GetFloppyCount; 150 MachVtbl.DiskReadLogicalSectors = Pc98DiskReadLogicalSectors; 151 MachVtbl.DiskGetDriveGeometry = Pc98DiskGetDriveGeometry; 152 MachVtbl.DiskGetCacheableBlockCount = Pc98DiskGetCacheableBlockCount; 153 MachVtbl.GetTime = Pc98GetTime; 154 MachVtbl.InitializeBootDevices = Pc98InitializeBootDevices; 155 MachVtbl.HwDetect = Pc98HwDetect; 156 MachVtbl.HwIdle = Pc98HwIdle; 157 158 HiResoMachine = *(PUCHAR)MEM_BIOS_FLAG1 & HIGH_RESOLUTION_FLAG; 159 160 HalpCalibrateStallExecution(); 161 Pc98VideoInit(); 162 } 163