mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 20:52:50 +00:00
[NTVDM]
- BIOS: Reorganize a bit the header, and close the input thread before closing the input handle (and not after). - INT32: Fix a comment. - CMOS: Put CMOS data into a structure called CMOS_MEMORY, introduce READ/WRITE_CMOS_DATA macros for simplifying code. Save CMOS memory into a file (à la Windows' NTVDM), which is loaded at startup. svn path=/branches/ntvdm/; revision=60913
This commit is contained in:
parent
fda5745543
commit
bf2731fb9f
7 changed files with 221 additions and 147 deletions
|
@ -568,6 +568,9 @@ BOOLEAN BiosInitialize(VOID)
|
|||
|
||||
VOID BiosCleanup(VOID)
|
||||
{
|
||||
/* Close the input thread handle */
|
||||
if (InputThread != NULL) CloseHandle(InputThread);
|
||||
|
||||
/* Restore the old screen buffer */
|
||||
SetConsoleActiveScreenBuffer(BiosConsoleOutput);
|
||||
|
||||
|
@ -577,9 +580,6 @@ VOID BiosCleanup(VOID)
|
|||
/* Close the console handles */
|
||||
if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput);
|
||||
if (BiosConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput);
|
||||
|
||||
/* Close the input thread handle */
|
||||
if (InputThread != NULL) CloseHandle(InputThread);
|
||||
}
|
||||
|
||||
WORD BiosPeekCharacter(VOID)
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
#define ROM_AREA_START 0xE0000
|
||||
#define ROM_AREA_END 0xFFFFF
|
||||
#define ROM_AREA_START 0xE0000
|
||||
#define ROM_AREA_END 0xFFFFF
|
||||
|
||||
#define BDA_SEGMENT 0x40
|
||||
#define BIOS_SEGMENT 0xF000
|
||||
|
@ -34,13 +34,15 @@
|
|||
#define CONSOLE_FONT_HEIGHT 8
|
||||
#define BIOS_KBD_BUFFER_SIZE 16
|
||||
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
|
||||
|
||||
#define BIOS_DEFAULT_VIDEO_MODE 0x03
|
||||
#define BIOS_MAX_PAGES 8
|
||||
#define BIOS_PAGE_SIZE 0x1000
|
||||
#define BIOS_MAX_VIDEO_MODE 0x13
|
||||
#define DEFAULT_ATTRIBUTE 0x07
|
||||
#define GRAPHICS_VIDEO_SEG 0xA000
|
||||
#define TEXT_VIDEO_SEG 0xB800
|
||||
#define DEFAULT_ATTRIBUTE 0x07
|
||||
|
||||
#define GRAPHICS_VIDEO_SEG 0xA000
|
||||
#define TEXT_VIDEO_SEG 0xB800
|
||||
|
||||
#define BDA_KBDFLAG_RSHIFT (1 << 0)
|
||||
#define BDA_KBDFLAG_LSHIFT (1 << 1)
|
||||
|
@ -67,8 +69,6 @@ enum
|
|||
SCROLL_DIRECTION_RIGHT
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/*
|
||||
* BIOS Data Area at 0040:XXXX
|
||||
*
|
||||
|
@ -76,6 +76,7 @@ enum
|
|||
* and: http://www.bioscentral.com/misc/bda.htm
|
||||
* for more information.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
WORD SerialPorts[4]; // 0x00
|
||||
|
@ -142,11 +143,10 @@ typedef struct
|
|||
BYTE Reserved17[15]; // 0x121
|
||||
BYTE Reserved18[3]; // 0x130
|
||||
} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
|
||||
#pragma pack(pop)
|
||||
|
||||
C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
extern PBIOS_DATA_AREA Bda;
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
static HANDLE hCmosRam = INVALID_HANDLE_VALUE;
|
||||
static CMOS_MEMORY CmosMemory;
|
||||
|
||||
static BOOLEAN NmiEnabled = TRUE;
|
||||
static BYTE StatusRegA = CMOS_DEFAULT_STA;
|
||||
static BYTE StatusRegB = CMOS_DEFAULT_STB;
|
||||
static BYTE StatusRegC = 0;
|
||||
static BYTE AlarmHour, AlarmMinute, AlarmSecond;
|
||||
static CMOS_REGISTERS SelectedRegister = CMOS_REG_STATUS_D;
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
@ -59,45 +58,29 @@ BYTE CmosReadData(VOID)
|
|||
switch (SelectedRegister)
|
||||
{
|
||||
case CMOS_REG_SECONDS:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? CurrentTime.wSecond
|
||||
: BINARY_TO_BCD(CurrentTime.wSecond);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wSecond);
|
||||
|
||||
case CMOS_REG_ALARM_SEC:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? AlarmSecond
|
||||
: BINARY_TO_BCD(AlarmSecond);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmSecond);
|
||||
|
||||
case CMOS_REG_MINUTES:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? CurrentTime.wMinute
|
||||
: BINARY_TO_BCD(CurrentTime.wMinute);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wMinute);
|
||||
|
||||
case CMOS_REG_ALARM_MIN:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? AlarmMinute
|
||||
: BINARY_TO_BCD(AlarmMinute);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmMinute);
|
||||
|
||||
case CMOS_REG_HOURS:
|
||||
{
|
||||
BOOLEAN Afternoon = FALSE;
|
||||
BYTE Value = CurrentTime.wHour;
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
|
||||
if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
|
||||
{
|
||||
Value -= 12;
|
||||
Afternoon = TRUE;
|
||||
}
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_BINARY)) Value = BINARY_TO_BCD(Value);
|
||||
Value = READ_CMOS_DATA(CmosMemory, Value);
|
||||
|
||||
/* Convert to 12-hour */
|
||||
if (Afternoon) Value |= 0x80;
|
||||
|
@ -108,15 +91,15 @@ BYTE CmosReadData(VOID)
|
|||
case CMOS_REG_ALARM_HRS:
|
||||
{
|
||||
BOOLEAN Afternoon = FALSE;
|
||||
BYTE Value = AlarmHour;
|
||||
BYTE Value = CmosMemory.AlarmHour;
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
|
||||
if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12))
|
||||
{
|
||||
Value -= 12;
|
||||
Afternoon = TRUE;
|
||||
}
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_BINARY)) Value = BINARY_TO_BCD(Value);
|
||||
Value = READ_CMOS_DATA(CmosMemory, Value);
|
||||
|
||||
/* Convert to 12-hour */
|
||||
if (Afternoon) Value |= 0x80;
|
||||
|
@ -125,70 +108,42 @@ BYTE CmosReadData(VOID)
|
|||
}
|
||||
|
||||
case CMOS_REG_DAY_OF_WEEK:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? CurrentTime.wDayOfWeek
|
||||
: BINARY_TO_BCD(CurrentTime.wDayOfWeek);
|
||||
}
|
||||
/*
|
||||
* The CMOS value is 1-based but the
|
||||
* GetLocalTime API value is 0-based.
|
||||
* Correct it.
|
||||
*/
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wDayOfWeek + 1);
|
||||
|
||||
case CMOS_REG_DAY:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? CurrentTime.wDay
|
||||
:BINARY_TO_BCD(CurrentTime.wDay);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wDay);
|
||||
|
||||
case CMOS_REG_MONTH:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? CurrentTime.wMonth
|
||||
: BINARY_TO_BCD(CurrentTime.wMonth);
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wMonth);
|
||||
|
||||
case CMOS_REG_YEAR:
|
||||
{
|
||||
return (StatusRegB & CMOS_STB_BINARY)
|
||||
? (CurrentTime.wYear % 100)
|
||||
: BINARY_TO_BCD(CurrentTime.wYear % 100);
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_A:
|
||||
{
|
||||
return StatusRegA;
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_B:
|
||||
{
|
||||
return StatusRegB;
|
||||
}
|
||||
return READ_CMOS_DATA(CmosMemory, CurrentTime.wYear % 100);
|
||||
|
||||
case CMOS_REG_STATUS_C:
|
||||
{
|
||||
BYTE Value = StatusRegC;
|
||||
BYTE Value = CmosMemory.StatusRegC;
|
||||
|
||||
/* Clear status register C */
|
||||
StatusRegC = 0;
|
||||
CmosMemory.StatusRegC = 0x00;
|
||||
|
||||
/* Return the old value */
|
||||
return Value;
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_A:
|
||||
case CMOS_REG_STATUS_B:
|
||||
case CMOS_REG_STATUS_D:
|
||||
{
|
||||
/* Our CMOS battery works perfectly forever */
|
||||
return CMOS_BATTERY_OK;
|
||||
}
|
||||
|
||||
case CMOS_REG_DIAGNOSTICS:
|
||||
{
|
||||
/* Diagnostics found no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CMOS_REG_SHUTDOWN_STATUS:
|
||||
default:
|
||||
{
|
||||
/* Read ignored */
|
||||
return 0;
|
||||
// ASSERT(SelectedRegister < CMOS_REG_MAX);
|
||||
return CmosMemory.Regs[SelectedRegister];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,38 +164,26 @@ VOID CmosWriteData(BYTE Value)
|
|||
case CMOS_REG_SECONDS:
|
||||
{
|
||||
ChangeTime = TRUE;
|
||||
CurrentTime.wSecond = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CurrentTime.wSecond = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_ALARM_SEC:
|
||||
{
|
||||
AlarmSecond = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CmosMemory.AlarmSecond = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_MINUTES:
|
||||
{
|
||||
ChangeTime = TRUE;
|
||||
CurrentTime.wMinute = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CurrentTime.wMinute = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_ALARM_MIN:
|
||||
{
|
||||
AlarmMinute = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CmosMemory.AlarmMinute = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -250,15 +193,13 @@ VOID CmosWriteData(BYTE Value)
|
|||
|
||||
ChangeTime = TRUE;
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
|
||||
if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
|
||||
{
|
||||
Value &= ~0x80;
|
||||
Afternoon = TRUE;
|
||||
}
|
||||
|
||||
CurrentTime.wHour = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
CurrentTime.wHour = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
|
||||
/* Convert to 24-hour format */
|
||||
if (Afternoon) CurrentTime.wHour += 12;
|
||||
|
@ -270,18 +211,16 @@ VOID CmosWriteData(BYTE Value)
|
|||
{
|
||||
BOOLEAN Afternoon = FALSE;
|
||||
|
||||
if (!(StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
|
||||
if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80))
|
||||
{
|
||||
Value &= ~0x80;
|
||||
Afternoon = TRUE;
|
||||
}
|
||||
|
||||
AlarmHour = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
CmosMemory.AlarmHour = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
|
||||
/* Convert to 24-hour format */
|
||||
if (Afternoon) AlarmHour += 12;
|
||||
if (Afternoon) CmosMemory.AlarmHour += 12;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -289,30 +228,27 @@ VOID CmosWriteData(BYTE Value)
|
|||
case CMOS_REG_DAY_OF_WEEK:
|
||||
{
|
||||
ChangeTime = TRUE;
|
||||
CurrentTime.wDayOfWeek = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
/*
|
||||
* The CMOS value is 1-based but the
|
||||
* SetLocalTime API value is 0-based.
|
||||
* Correct it.
|
||||
*/
|
||||
Value -= 1;
|
||||
CurrentTime.wDayOfWeek = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_DAY:
|
||||
{
|
||||
ChangeTime = TRUE;
|
||||
CurrentTime.wDay = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CurrentTime.wDay = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_MONTH:
|
||||
{
|
||||
ChangeTime = TRUE;
|
||||
CurrentTime.wMonth = (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CurrentTime.wMonth = WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -323,28 +259,30 @@ VOID CmosWriteData(BYTE Value)
|
|||
/* Clear everything except the century */
|
||||
CurrentTime.wYear = (CurrentTime.wYear / 100) * 100;
|
||||
|
||||
CurrentTime.wYear += (StatusRegB & CMOS_STB_BINARY)
|
||||
? Value
|
||||
: BCD_TO_BINARY(Value);
|
||||
|
||||
CurrentTime.wYear += WRITE_CMOS_DATA(CmosMemory, Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_A:
|
||||
{
|
||||
StatusRegA = Value;
|
||||
CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_B:
|
||||
{
|
||||
StatusRegB = Value;
|
||||
CmosMemory.StatusRegB = Value;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMOS_REG_STATUS_C:
|
||||
case CMOS_REG_STATUS_D:
|
||||
// Status registers C and D are read-only
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
/* Write ignored */
|
||||
CmosMemory.Regs[SelectedRegister] = Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,7 +294,7 @@ VOID CmosWriteData(BYTE Value)
|
|||
|
||||
DWORD RtcGetTicksPerSecond(VOID)
|
||||
{
|
||||
BYTE RateSelect = StatusRegB & 0x0F;
|
||||
BYTE RateSelect = CmosMemory.StatusRegB & 0x0F;
|
||||
|
||||
if (RateSelect == 0)
|
||||
{
|
||||
|
@ -373,12 +311,12 @@ DWORD RtcGetTicksPerSecond(VOID)
|
|||
VOID RtcPeriodicTick(VOID)
|
||||
{
|
||||
/* Set PF */
|
||||
StatusRegC |= CMOS_STC_PF;
|
||||
CmosMemory.StatusRegC |= CMOS_STC_PF;
|
||||
|
||||
/* Check if there should be an interrupt on a periodic timer tick */
|
||||
if (StatusRegB & CMOS_STB_INT_PERIODIC)
|
||||
if (CmosMemory.StatusRegB & CMOS_STB_INT_PERIODIC)
|
||||
{
|
||||
StatusRegC |= CMOS_STC_IRQF;
|
||||
CmosMemory.StatusRegC |= CMOS_STC_IRQF;
|
||||
|
||||
/* Interrupt! */
|
||||
PicInterruptRequest(RTC_IRQ_NUMBER);
|
||||
|
@ -394,26 +332,91 @@ VOID RtcTimeUpdate(VOID)
|
|||
GetLocalTime(&CurrentTime);
|
||||
|
||||
/* Set UF */
|
||||
StatusRegC |= CMOS_STC_UF;
|
||||
CmosMemory.StatusRegC |= CMOS_STC_UF;
|
||||
|
||||
/* Check if the time matches the alarm time */
|
||||
if ((CurrentTime.wHour == AlarmHour)
|
||||
&& (CurrentTime.wMinute == AlarmMinute)
|
||||
&& (CurrentTime.wSecond == AlarmSecond))
|
||||
if ((CurrentTime.wHour == CmosMemory.AlarmHour ) &&
|
||||
(CurrentTime.wMinute == CmosMemory.AlarmMinute) &&
|
||||
(CurrentTime.wSecond == CmosMemory.AlarmSecond))
|
||||
{
|
||||
/* Set the alarm flag */
|
||||
StatusRegC |= CMOS_STC_AF;
|
||||
CmosMemory.StatusRegC |= CMOS_STC_AF;
|
||||
|
||||
/* Set IRQF if there should be an interrupt */
|
||||
if (StatusRegB & CMOS_STB_INT_ON_ALARM) StatusRegC |= CMOS_STC_IRQF;
|
||||
if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_ALARM) CmosMemory.StatusRegC |= CMOS_STC_IRQF;
|
||||
}
|
||||
|
||||
/* Check if there should be an interrupt on update */
|
||||
if (StatusRegB & CMOS_STB_INT_ON_UPDATE) StatusRegC |= CMOS_STC_IRQF;
|
||||
if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_UPDATE) CmosMemory.StatusRegC |= CMOS_STC_IRQF;
|
||||
|
||||
if (StatusRegC & CMOS_STC_IRQF)
|
||||
if (CmosMemory.StatusRegC & CMOS_STC_IRQF)
|
||||
{
|
||||
/* Interrupt! */
|
||||
PicInterruptRequest(RTC_IRQ_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN CmosInitialize(VOID)
|
||||
{
|
||||
DWORD CmosSize = sizeof(CmosMemory);
|
||||
|
||||
/* File must not be opened before */
|
||||
ASSERT(hCmosRam == INVALID_HANDLE_VALUE);
|
||||
|
||||
/* Clear the CMOS memory */
|
||||
ZeroMemory(&CmosMemory, sizeof(CmosMemory));
|
||||
|
||||
/* Always open (and if needed, create) a RAM file with exclusive access */
|
||||
SetLastError(0); // For debugging purposes
|
||||
hCmosRam = CreateFileW(L"cmos.ram",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
DPRINT1("CMOS opening %s ; GetLastError() = %u\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError());
|
||||
|
||||
if (hCmosRam != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
BOOL Success = FALSE;
|
||||
|
||||
/* Attempt to fill the CMOS memory with the RAM file */
|
||||
SetLastError(0); // For debugging purposes
|
||||
Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
|
||||
if (CmosSize != sizeof(CmosMemory))
|
||||
{
|
||||
/* Bad CMOS Ram file. Reinitialize the CMOS memory. */
|
||||
DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n", CmosSize, sizeof(CmosMemory));
|
||||
ZeroMemory(&CmosMemory, sizeof(CmosMemory));
|
||||
}
|
||||
DPRINT1("CMOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
||||
SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
|
||||
}
|
||||
|
||||
/* Overwrite some registers with default values */
|
||||
CmosMemory.StatusRegA = CMOS_DEFAULT_STA;
|
||||
CmosMemory.StatusRegB = CMOS_DEFAULT_STB;
|
||||
CmosMemory.StatusRegC = 0x00;
|
||||
CmosMemory.StatusRegD = CMOS_BATTERY_OK; // Our CMOS battery works perfectly forever.
|
||||
CmosMemory.Diagnostics = 0x00; // Diagnostics must not find any errors.
|
||||
CmosMemory.ShutdownStatus = 0x00;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID CmosCleanup(VOID)
|
||||
{
|
||||
DWORD CmosSize = sizeof(CmosMemory);
|
||||
|
||||
if (hCmosRam == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
/* Flush the CMOS memory back to the RAM file and close it */
|
||||
SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
|
||||
WriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
|
||||
|
||||
CloseHandle(hCmosRam);
|
||||
hCmosRam = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Virtual DOS Machine
|
||||
* FILE: cmos.h
|
||||
* PURPOSE: Real Time Clock emulation (header file)
|
||||
* PURPOSE: CMOS Real Time Clock emulation
|
||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
|
@ -43,6 +43,12 @@
|
|||
#define BINARY_TO_BCD(x) (((x / 10) << 4) | (x % 10))
|
||||
#define BCD_TO_BINARY(x) (((x >> 4) * 10) + (x & 0x0F))
|
||||
|
||||
#define WRITE_CMOS_DATA(Cmos, Value) \
|
||||
((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value)
|
||||
|
||||
#define READ_CMOS_DATA(Cmos, Value) \
|
||||
((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BINARY_TO_BCD(Value)
|
||||
|
||||
typedef enum _CMOS_REGISTERS
|
||||
{
|
||||
CMOS_REG_SECONDS,
|
||||
|
@ -60,9 +66,63 @@ typedef enum _CMOS_REGISTERS
|
|||
CMOS_REG_STATUS_C,
|
||||
CMOS_REG_STATUS_D,
|
||||
CMOS_REG_DIAGNOSTICS,
|
||||
CMOS_REG_MAX
|
||||
CMOS_REG_SHUTDOWN_STATUS,
|
||||
CMOS_REG_MAX = 0x40
|
||||
} CMOS_REGISTERS, *PCMOS_REGISTERS;
|
||||
|
||||
|
||||
/*
|
||||
* CMOS Memory Map
|
||||
*
|
||||
* See the following documentation for more information:
|
||||
* http://www.intel-assembler.it/portale/5/cmos-memory-map-123/cmos-memory-map-123.asp
|
||||
* http://wiki.osdev.org/CMOS
|
||||
* http://www.bioscentral.com/misc/cmosmap.htm
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
BYTE Second; // 0x00
|
||||
BYTE AlarmSecond; // 0x01
|
||||
BYTE Minute; // 0x02
|
||||
BYTE AlarmMinute; // 0x03
|
||||
BYTE Hour; // 0x04
|
||||
BYTE AlarmHour; // 0x05
|
||||
BYTE DayOfWeek; // 0x06
|
||||
BYTE Day; // 0x07
|
||||
BYTE Month; // 0x08
|
||||
BYTE Year; // 0x09
|
||||
|
||||
BYTE StatusRegA; // 0x0a
|
||||
BYTE StatusRegB; // 0x0b
|
||||
} CMOS_CLOCK, *PCMOS_CLOCK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
CMOS_CLOCK; // 0x00 - 0x0b
|
||||
BYTE StatusRegC; // 0x0c
|
||||
BYTE StatusRegD; // 0x0d
|
||||
BYTE Diagnostics; // 0x0e
|
||||
BYTE ShutdownStatus; // 0x0f
|
||||
};
|
||||
BYTE Regs1[0x10]; // 0x00 - 0x0f
|
||||
BYTE Regs [0x40]; // 0x00 - 0x3f
|
||||
};
|
||||
|
||||
/*
|
||||
* Extended information 0x40 - 0x7f
|
||||
*/
|
||||
} CMOS_MEMORY, *PCMOS_MEMORY;
|
||||
#pragma pack(pop)
|
||||
|
||||
C_ASSERT(sizeof(CMOS_MEMORY) == 0x40);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN IsNmiEnabled(VOID);
|
||||
VOID CmosWriteAddress(BYTE Value);
|
||||
BYTE CmosReadData(VOID);
|
||||
|
@ -70,7 +130,10 @@ VOID CmosWriteData(BYTE Value);
|
|||
DWORD RtcGetTicksPerSecond(VOID);
|
||||
VOID RtcPeriodicTick(VOID);
|
||||
VOID RtcTimeUpdate(VOID);
|
||||
|
||||
|
||||
BOOLEAN CmosInitialize(VOID);
|
||||
VOID CmosCleanup(VOID);
|
||||
|
||||
#endif // _CMOS_H_
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "cmos.h"
|
||||
#include "bios.h"
|
||||
#include "bop.h"
|
||||
#include "dos.h"
|
||||
|
@ -19,7 +20,6 @@
|
|||
#include "pic.h"
|
||||
#include "ps2.h"
|
||||
#include "timer.h"
|
||||
#include "cmos.h"
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ VOID WINAPI InitializeInt32(WORD BiosSegment)
|
|||
// HACK: The following instruction should be HLT!
|
||||
BiosCode[Offset++] = 0x90; // nop
|
||||
|
||||
BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10)
|
||||
BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11)
|
||||
BiosCode[Offset++] = 0xF5;
|
||||
|
||||
// EXIT:
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "ntvdm.h"
|
||||
#include "emulator.h"
|
||||
#include "cmos.h"
|
||||
#include "bios.h"
|
||||
#include "speaker.h"
|
||||
#include "vga.h"
|
||||
|
@ -19,7 +20,6 @@
|
|||
#include "timer.h"
|
||||
#include "pic.h"
|
||||
#include "ps2.h"
|
||||
#include "cmos.h"
|
||||
|
||||
/*
|
||||
* Activate this line if you want to be able to test NTVDM with:
|
||||
|
@ -117,6 +117,13 @@ INT wmain(INT argc, WCHAR *argv[])
|
|||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Initialize the CMOS */
|
||||
if (!CmosInitialize())
|
||||
{
|
||||
wprintf(L"FATAL: Failed to initialize the VDM CMOS.\n");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Initialize the system BIOS */
|
||||
if (!BiosInitialize())
|
||||
{
|
||||
|
@ -227,6 +234,7 @@ INT wmain(INT argc, WCHAR *argv[])
|
|||
Cleanup:
|
||||
SpeakerCleanup();
|
||||
BiosCleanup();
|
||||
CmosCleanup();
|
||||
EmulatorCleanup();
|
||||
|
||||
DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue