01ce601bdb
Convert all DEBUG_SMBUS, DEBUG_SMI, and DEBUG_RAM_SETUP custom and local #defines into globally configurable kconfig options (and Options.lb options for as long as newconfig still exists) which can be enabled by the user in the "Debugging" menu. The respective menu items only appear if a board is selected where the chipset code actually provides such additional DEBUG output. All three variables default to 0 / off for now. Also, drop a small chunk of dead/useless code in the src/northbridge/via/cn700/raminit.c file, which would otherwise break compilation. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Reworked to still apply to trunk, added X86EMU_DEBUG (and make the x86emu/yabel code only work printf instead of a redefined version of printk and Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5185 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
496 lines
16 KiB
C
496 lines
16 KiB
C
/******************************************************************************
|
|
* Copyright (c) 2004, 2008 IBM Corporation
|
|
* Copyright (c) 2009 Pattrick Hueper <phueper@hueper.net>
|
|
* All rights reserved.
|
|
* This program and the accompanying materials
|
|
* are made available under the terms of the BSD License
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.opensource.org/licenses/bsd-license.php
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial implementation
|
|
*****************************************************************************/
|
|
|
|
#include <types.h>
|
|
#include "debug.h"
|
|
#include "device.h"
|
|
#include "x86emu/x86emu.h"
|
|
#include "biosemu.h"
|
|
#include "mem.h"
|
|
#include "compat/time.h"
|
|
|
|
// define a check for access to certain (virtual) memory regions (interrupt handlers, BIOS Data Area, ...)
|
|
#if CONFIG_X86EMU_DEBUG
|
|
static u8 in_check = 0; // to avoid recursion...
|
|
u16 ebda_segment;
|
|
u32 ebda_size;
|
|
|
|
//TODO: these macros have grown so large, that they should be changed to an inline function,
|
|
//just for the sake of readability...
|
|
|
|
#define DEBUG_CHECK_VMEM_READ(_addr, _rval) \
|
|
if ((debug_flags & DEBUG_CHECK_VMEM_ACCESS) && (in_check == 0)) { \
|
|
in_check = 1; \
|
|
/* determine ebda_segment and size \
|
|
* since we are using my_rdx calls, make sure, this is after setting in_check! */ \
|
|
/* offset 03 in BDA is EBDA segment */ \
|
|
ebda_segment = my_rdw(0x40e); \
|
|
/* first value in ebda is size in KB */ \
|
|
ebda_size = my_rdb(ebda_segment << 4) * 1024; \
|
|
/* check Interrupt Vector Access (0000:0000h - 0000:0400h) */ \
|
|
if (_addr < 0x400) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from Interrupt Vector %x --> %x\n", \
|
|
__func__, _addr / 4, _rval); \
|
|
} \
|
|
/* access to BIOS Data Area (0000:0400h - 0000:0500h)*/ \
|
|
else if ((_addr >= 0x400) && (addr < 0x500)) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from BIOS Data Area: addr: %x --> %x\n", \
|
|
__func__, _addr, _rval); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* access to first 64k of memory... */ \
|
|
else if (_addr < 0x10000) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from segment 0000h: addr: %x --> %x\n", \
|
|
__func__, _addr, _rval); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* read from PMM_CONV_SEGMENT */ \
|
|
else if ((_addr <= ((PMM_CONV_SEGMENT << 4) | 0xffff)) && (_addr >= (PMM_CONV_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from PMM Segment %04xh: addr: %x --> %x\n", \
|
|
__func__, PMM_CONV_SEGMENT, _addr, _rval); \
|
|
/* HALT_SYS(); */ \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* read from PNP_DATA_SEGMENT */ \
|
|
else if ((_addr <= ((PNP_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (PNP_DATA_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from PnP Data Segment %04xh: addr: %x --> %x\n", \
|
|
__func__, PNP_DATA_SEGMENT, _addr, _rval); \
|
|
/* HALT_SYS(); */ \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* read from EBDA Segment */ \
|
|
else if ((_addr <= ((ebda_segment << 4) | (ebda_size - 1))) && (_addr >= (ebda_segment << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from Extended BIOS Data Area %04xh, size: %04x: addr: %x --> %x\n", \
|
|
__func__, ebda_segment, ebda_size, _addr, _rval); \
|
|
} \
|
|
/* read from BIOS_DATA_SEGMENT */ \
|
|
else if ((_addr <= ((BIOS_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (BIOS_DATA_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: read from BIOS Data Segment %04xh: addr: %x --> %x\n", \
|
|
__func__, BIOS_DATA_SEGMENT, _addr, _rval); \
|
|
/* for PMM debugging */ \
|
|
/*if (_addr == BIOS_DATA_SEGMENT << 4) { \
|
|
X86EMU_trace_on(); \
|
|
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; \
|
|
}*/ \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
in_check = 0; \
|
|
}
|
|
#define DEBUG_CHECK_VMEM_WRITE(_addr, _val) \
|
|
if ((debug_flags & DEBUG_CHECK_VMEM_ACCESS) && (in_check == 0)) { \
|
|
in_check = 1; \
|
|
/* determine ebda_segment and size \
|
|
* since we are using my_rdx calls, make sure, this is after setting in_check! */ \
|
|
/* offset 03 in BDA is EBDA segment */ \
|
|
ebda_segment = my_rdw(0x40e); \
|
|
/* first value in ebda is size in KB */ \
|
|
ebda_size = my_rdb(ebda_segment << 4) * 1024; \
|
|
/* check Interrupt Vector Access (0000:0000h - 0000:0400h) */ \
|
|
if (_addr < 0x400) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to Interrupt Vector %x <-- %x\n", \
|
|
__func__, _addr / 4, _val); \
|
|
} \
|
|
/* access to BIOS Data Area (0000:0400h - 0000:0500h)*/ \
|
|
else if ((_addr >= 0x400) && (addr < 0x500)) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to BIOS Data Area: addr: %x <-- %x\n", \
|
|
__func__, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* access to first 64k of memory...*/ \
|
|
else if (_addr < 0x10000) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to segment 0000h: addr: %x <-- %x\n", \
|
|
__func__, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* write to PMM_CONV_SEGMENT... */ \
|
|
else if ((_addr <= ((PMM_CONV_SEGMENT << 4) | 0xffff)) && (_addr >= (PMM_CONV_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to PMM Segment %04xh: addr: %x <-- %x\n", \
|
|
__func__, PMM_CONV_SEGMENT, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* write to PNP_DATA_SEGMENT... */ \
|
|
else if ((_addr <= ((PNP_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (PNP_DATA_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to PnP Data Segment %04xh: addr: %x <-- %x\n", \
|
|
__func__, PNP_DATA_SEGMENT, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* write to EBDA Segment... */ \
|
|
else if ((_addr <= ((ebda_segment << 4) | (ebda_size - 1))) && (_addr >= (ebda_segment << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to Extended BIOS Data Area %04xh, size: %04x: addr: %x <-- %x\n", \
|
|
__func__, ebda_segment, ebda_size, _addr, _val); \
|
|
} \
|
|
/* write to BIOS_DATA_SEGMENT... */ \
|
|
else if ((_addr <= ((BIOS_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (BIOS_DATA_SEGMENT << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to BIOS Data Segment %04xh: addr: %x <-- %x\n", \
|
|
__func__, BIOS_DATA_SEGMENT, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
/* write to current CS segment... */ \
|
|
else if ((_addr < ((M.x86.R_CS << 4) | 0xffff)) && (_addr > (M.x86.R_CS << 4))) { \
|
|
DEBUG_PRINTF_CS_IP("%s: write to CS segment %04xh: addr: %x <-- %x\n", \
|
|
__func__, M.x86.R_CS, _addr, _val); \
|
|
/* dump registers */ \
|
|
/* x86emu_dump_xregs(); */ \
|
|
} \
|
|
in_check = 0; \
|
|
}
|
|
#else
|
|
#define DEBUG_CHECK_VMEM_READ(_addr, _rval)
|
|
#define DEBUG_CHECK_VMEM_WRITE(_addr, _val)
|
|
#endif
|
|
|
|
//defined in net-snk/kernel/timer.c
|
|
extern u64 get_time(void);
|
|
|
|
void update_time(u32);
|
|
|
|
#if !defined(CONFIG_YABEL_DIRECTHW) || (!CONFIG_YABEL_DIRECTHW)
|
|
// read byte from memory
|
|
u8
|
|
my_rdb(u32 addr)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
u8 rval;
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
|
|
__func__, addr);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
set_ci();
|
|
rval = *((u8 *) translated_addr);
|
|
clr_ci();
|
|
DEBUG_PRINTF_MEM("%s(%08x) VGA --> %02x\n", __func__, addr,
|
|
rval);
|
|
return rval;
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* read from virtual memory */
|
|
rval = *((u8 *) (M.mem_base + addr));
|
|
DEBUG_CHECK_VMEM_READ(addr, rval);
|
|
return rval;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//read word from memory
|
|
u16
|
|
my_rdw(u32 addr)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
u16 rval;
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
|
|
__func__, addr);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
// check for legacy memory, because of the remapping to BARs, the reads must
|
|
// be byte reads...
|
|
if ((addr >= 0xa0000) && (addr < 0xc0000)) {
|
|
//read bytes a using my_rdb, because of the remapping to BARs
|
|
//words may not be contiguous in memory, so we need to translate
|
|
//every address...
|
|
rval = ((u8) my_rdb(addr)) |
|
|
(((u8) my_rdb(addr + 1)) << 8);
|
|
} else {
|
|
if ((translated_addr & (u64) 0x1) == 0) {
|
|
// 16 bit aligned access...
|
|
set_ci();
|
|
rval = in16le((void *) translated_addr);
|
|
clr_ci();
|
|
} else {
|
|
// unaligned access, read single bytes
|
|
set_ci();
|
|
rval = (*((u8 *) translated_addr)) |
|
|
(*((u8 *) translated_addr + 1) << 8);
|
|
clr_ci();
|
|
}
|
|
}
|
|
DEBUG_PRINTF_MEM("%s(%08x) VGA --> %04x\n", __func__, addr,
|
|
rval);
|
|
return rval;
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* read from virtual memory */
|
|
rval = in16le((void *) (M.mem_base + addr));
|
|
DEBUG_CHECK_VMEM_READ(addr, rval);
|
|
return rval;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//read long from memory
|
|
u32
|
|
my_rdl(u32 addr)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
u32 rval;
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%x): access to VGA Memory\n",
|
|
__func__, addr);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
// check for legacy memory, because of the remapping to BARs, the reads must
|
|
// be byte reads...
|
|
if ((addr >= 0xa0000) && (addr < 0xc0000)) {
|
|
//read bytes a using my_rdb, because of the remapping to BARs
|
|
//dwords may not be contiguous in memory, so we need to translate
|
|
//every address...
|
|
rval = ((u8) my_rdb(addr)) |
|
|
(((u8) my_rdb(addr + 1)) << 8) |
|
|
(((u8) my_rdb(addr + 2)) << 16) |
|
|
(((u8) my_rdb(addr + 3)) << 24);
|
|
} else {
|
|
if ((translated_addr & (u64) 0x3) == 0) {
|
|
// 32 bit aligned access...
|
|
set_ci();
|
|
rval = in32le((void *) translated_addr);
|
|
clr_ci();
|
|
} else {
|
|
// unaligned access, read single bytes
|
|
set_ci();
|
|
rval = (*((u8 *) translated_addr)) |
|
|
(*((u8 *) translated_addr + 1) << 8) |
|
|
(*((u8 *) translated_addr + 2) << 16) |
|
|
(*((u8 *) translated_addr + 3) << 24);
|
|
clr_ci();
|
|
}
|
|
}
|
|
DEBUG_PRINTF_MEM("%s(%08x) VGA --> %08x\n", __func__, addr,
|
|
rval);
|
|
//HALT_SYS();
|
|
return rval;
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* read from virtual memory */
|
|
rval = in32le((void *) (M.mem_base + addr));
|
|
switch (addr) {
|
|
case 0x46c:
|
|
//BDA Time Data, update it, before reading
|
|
update_time(rval);
|
|
rval = in32le((void *) (M.mem_base + addr));
|
|
break;
|
|
}
|
|
DEBUG_CHECK_VMEM_READ(addr, rval);
|
|
return rval;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//write byte to memory
|
|
void
|
|
my_wrb(u32 addr, u8 val)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
|
|
__func__, addr, val);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
set_ci();
|
|
*((u8 *) translated_addr) = val;
|
|
clr_ci();
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* write to virtual memory */
|
|
DEBUG_CHECK_VMEM_WRITE(addr, val);
|
|
*((u8 *) (M.mem_base + addr)) = val;
|
|
}
|
|
}
|
|
|
|
void
|
|
my_wrw(u32 addr, u16 val)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
|
|
__func__, addr, val);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
// check for legacy memory, because of the remapping to BARs, the reads must
|
|
// be byte reads...
|
|
if ((addr >= 0xa0000) && (addr < 0xc0000)) {
|
|
//read bytes a using my_rdb, because of the remapping to BARs
|
|
//words may not be contiguous in memory, so we need to translate
|
|
//every address...
|
|
my_wrb(addr, (u8) (val & 0x00FF));
|
|
my_wrb(addr + 1, (u8) ((val & 0xFF00) >> 8));
|
|
} else {
|
|
if ((translated_addr & (u64) 0x1) == 0) {
|
|
// 16 bit aligned access...
|
|
set_ci();
|
|
out16le((void *) translated_addr, val);
|
|
clr_ci();
|
|
} else {
|
|
// unaligned access, write single bytes
|
|
set_ci();
|
|
*((u8 *) translated_addr) =
|
|
(u8) (val & 0x00FF);
|
|
*((u8 *) translated_addr + 1) =
|
|
(u8) ((val & 0xFF00) >> 8);
|
|
clr_ci();
|
|
}
|
|
}
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* write to virtual memory */
|
|
DEBUG_CHECK_VMEM_WRITE(addr, val);
|
|
out16le((void *) (M.mem_base + addr), val);
|
|
}
|
|
}
|
|
void
|
|
my_wrl(u32 addr, u32 val)
|
|
{
|
|
unsigned long translated_addr = addr;
|
|
u8 translated = biosemu_dev_translate_address(&translated_addr);
|
|
if (translated != 0) {
|
|
//translation successfull, access VGA Memory (BAR or Legacy...)
|
|
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
|
|
__func__, addr, val);
|
|
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __func__, addr, translated_addr);
|
|
// check for legacy memory, because of the remapping to BARs, the reads must
|
|
// be byte reads...
|
|
if ((addr >= 0xa0000) && (addr < 0xc0000)) {
|
|
//read bytes a using my_rdb, because of the remapping to BARs
|
|
//words may not be contiguous in memory, so we need to translate
|
|
//every address...
|
|
my_wrb(addr, (u8) (val & 0x000000FF));
|
|
my_wrb(addr + 1, (u8) ((val & 0x0000FF00) >> 8));
|
|
my_wrb(addr + 2, (u8) ((val & 0x00FF0000) >> 16));
|
|
my_wrb(addr + 3, (u8) ((val & 0xFF000000) >> 24));
|
|
} else {
|
|
if ((translated_addr & (u64) 0x3) == 0) {
|
|
// 32 bit aligned access...
|
|
set_ci();
|
|
out32le((void *) translated_addr, val);
|
|
clr_ci();
|
|
} else {
|
|
// unaligned access, write single bytes
|
|
set_ci();
|
|
*((u8 *) translated_addr) =
|
|
(u8) (val & 0x000000FF);
|
|
*((u8 *) translated_addr + 1) =
|
|
(u8) ((val & 0x0000FF00) >> 8);
|
|
*((u8 *) translated_addr + 2) =
|
|
(u8) ((val & 0x00FF0000) >> 16);
|
|
*((u8 *) translated_addr + 3) =
|
|
(u8) ((val & 0xFF000000) >> 24);
|
|
clr_ci();
|
|
}
|
|
}
|
|
} else if (addr > M.mem_size) {
|
|
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
|
|
__func__, addr);
|
|
//disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
|
|
HALT_SYS();
|
|
} else {
|
|
/* write to virtual memory */
|
|
DEBUG_CHECK_VMEM_WRITE(addr, val);
|
|
out32le((void *) (M.mem_base + addr), val);
|
|
}
|
|
}
|
|
#else
|
|
u8
|
|
my_rdb(u32 addr)
|
|
{
|
|
return rdb(addr);
|
|
}
|
|
|
|
u16
|
|
my_rdw(u32 addr)
|
|
{
|
|
return rdw(addr);
|
|
}
|
|
|
|
u32
|
|
my_rdl(u32 addr)
|
|
{
|
|
return rdl(addr);
|
|
}
|
|
|
|
void
|
|
my_wrb(u32 addr, u8 val)
|
|
{
|
|
wrb(addr, val);
|
|
}
|
|
|
|
void
|
|
my_wrw(u32 addr, u16 val)
|
|
{
|
|
wrw(addr, val);
|
|
}
|
|
|
|
void
|
|
my_wrl(u32 addr, u32 val)
|
|
{
|
|
wrl(addr, val);
|
|
}
|
|
#endif
|
|
|
|
//update time in BIOS Data Area
|
|
//DWord at offset 0x6c is the timer ticks since midnight, timer is running at 18Hz
|
|
//byte at 0x70 is timer overflow (set if midnight passed since last call to interrupt 1a function 00
|
|
//cur_val is the current value, of offset 6c...
|
|
void
|
|
update_time(u32 cur_val)
|
|
{
|
|
//for convenience, we let the start of timebase be at midnight, we currently dont support
|
|
//real daytime anyway...
|
|
u64 ticks_per_day = tb_freq * 60 * 24;
|
|
// at 18Hz a period is ~55ms, converted to ticks (tb_freq is ticks/second)
|
|
u32 period_ticks = (55 * tb_freq) / 1000;
|
|
u64 curr_time = get_time();
|
|
u64 ticks_since_midnight = curr_time % ticks_per_day;
|
|
u32 periods_since_midnight = ticks_since_midnight / period_ticks;
|
|
// if periods since midnight is smaller than last value, set overflow
|
|
// at BDA Offset 0x70
|
|
if (periods_since_midnight < cur_val) {
|
|
my_wrb(0x470, 1);
|
|
}
|
|
// store periods since midnight at BDA offset 0x6c
|
|
my_wrl(0x46c, periods_since_midnight);
|
|
}
|