- use symbolic names for cmos register numbers instead of hex numbers.
This rev does not make any functional change.
This commit is contained in:
parent
7cb4093e4a
commit
da9de3c72d
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cmos.cc,v 1.30 2002-12-06 22:22:32 bdenney Exp $
|
||||
// $Id: cmos.cc,v 1.31 2002-12-06 22:36:48 bdenney Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -39,6 +39,32 @@
|
||||
|
||||
bx_cmos_c *theCmosDevice = NULL;
|
||||
|
||||
// CMOS register definitions from Ralf Brown's interrupt list v6.1, in a file
|
||||
// called cmos.lst. In cases where there are multiple uses for a given
|
||||
// register in the interrupt list, I only listed the purpose that Bochs
|
||||
// actually uses it for, but I wrote "alternatives" next to it.
|
||||
#define REG_SEC 0x00
|
||||
#define REG_SEC_ALARM 0x01
|
||||
#define REG_MIN 0x02
|
||||
#define REG_MIN_ALARM 0x03
|
||||
#define REG_HOUR 0x04
|
||||
#define REG_HOUR_ALARM 0x05
|
||||
#define REG_WEEK_DAY 0x06
|
||||
#define REG_MONTH_DAY 0x07
|
||||
#define REG_MONTH 0x08
|
||||
#define REG_YEAR 0x09
|
||||
#define REG_STAT_A 0x0a
|
||||
#define REG_STAT_B 0x0b
|
||||
#define REG_STAT_C 0x0c
|
||||
#define REG_STAT_D 0x0d
|
||||
#define REG_DIAGNOSTIC_STATUS 0x0e /* alternatives */
|
||||
#define REG_SHUTDOWN_STATUS 0x0f
|
||||
#define REG_EQUIPMENT_BYTE 0x14
|
||||
#define REG_CSUM_HIGH 0x2e
|
||||
#define REG_CSUM_LOW 0x2f
|
||||
#define REG_IBM_CENTURY_BYTE 0x32 /* alternatives */
|
||||
#define REG_IBM_PS2_CENTURY_BYTE 0x37 /* alternatives */
|
||||
|
||||
// check that BX_NUM_CMOS_REGS is 64 or 128
|
||||
#if (BX_NUM_CMOS_REGS == 64)
|
||||
#elif (BX_NUM_CMOS_REGS == 128)
|
||||
@ -82,7 +108,7 @@ bx_cmos_c::~bx_cmos_c(void)
|
||||
void
|
||||
bx_cmos_c::init(void)
|
||||
{
|
||||
BX_DEBUG(("Init $Id: cmos.cc,v 1.30 2002-12-06 22:22:32 bdenney Exp $"));
|
||||
BX_DEBUG(("Init $Id: cmos.cc,v 1.31 2002-12-06 22:36:48 bdenney Exp $"));
|
||||
// CMOS RAM & RTC
|
||||
|
||||
DEV_register_ioread_handler(this, read_handler, 0x0070, "CMOS RAM", 7);
|
||||
@ -158,12 +184,12 @@ bx_cmos_c::init(void)
|
||||
}
|
||||
else {
|
||||
// CMOS values generated
|
||||
BX_CMOS_THIS s.reg[0x0a] = 0x26;
|
||||
BX_CMOS_THIS s.reg[0x0b] = 0x02;
|
||||
BX_CMOS_THIS s.reg[0x0c] = 0x00;
|
||||
BX_CMOS_THIS s.reg[0x0d] = 0x80;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_A] = 0x26;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_B] = 0x02;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_D] = 0x80;
|
||||
#if BX_SUPPORT_FPU == 1
|
||||
BX_CMOS_THIS s.reg[0x14] |= 0x02;
|
||||
BX_CMOS_THIS s.reg[REG_EQUIPMENT_BYTE] |= 0x02;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -178,8 +204,8 @@ bx_cmos_c::reset(unsigned type)
|
||||
// CRB: bits 4,5,6 forced to 0
|
||||
// CRC: bits 4,5,6,7 forced to 0
|
||||
// CRD: no effects
|
||||
BX_CMOS_THIS s.reg[0x0b] &= 0x8f;
|
||||
BX_CMOS_THIS s.reg[0x0c] = 0;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_B] &= 0x8f;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] = 0;
|
||||
|
||||
// One second timer for updating clock & alarm functions
|
||||
bx_pc_system.activate_timer(BX_CMOS_THIS s.one_second_timer_index,
|
||||
@ -195,7 +221,7 @@ bx_cmos_c::CRA_change(void)
|
||||
unsigned nibble;
|
||||
|
||||
// Periodic Interrupt timer
|
||||
nibble = BX_CMOS_THIS s.reg[0x0a] & 0x0f;
|
||||
nibble = BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f;
|
||||
if (nibble == 0) {
|
||||
// No Periodic Interrupt Rate when 0, deactivate timer
|
||||
bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index);
|
||||
@ -209,7 +235,7 @@ bx_cmos_c::CRA_change(void)
|
||||
(32768.0L / (1 << (nibble - 1))));
|
||||
|
||||
// if Periodic Interrupt Enable bit set, activate timer
|
||||
if ( BX_CMOS_THIS s.reg[0x0b] & 0x40 )
|
||||
if ( BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40 )
|
||||
bx_pc_system.activate_timer(BX_CMOS_THIS s.periodic_timer_index,
|
||||
BX_CMOS_THIS s.periodic_interval_usec, 1);
|
||||
else
|
||||
@ -262,8 +288,8 @@ bx_cmos_c::read(Bit32u address, unsigned io_len)
|
||||
|
||||
ret8 = BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address];
|
||||
// all bits of Register C are cleared after a read occurs.
|
||||
if (BX_CMOS_THIS s.cmos_mem_address == 0x0c) {
|
||||
BX_CMOS_THIS s.reg[0x0c] = 0x00;
|
||||
if (BX_CMOS_THIS s.cmos_mem_address == REG_STAT_C) {
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00;
|
||||
DEV_pic_lower_irq(8);
|
||||
}
|
||||
return(ret8);
|
||||
@ -322,18 +348,18 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
return;
|
||||
}
|
||||
switch (BX_CMOS_THIS s.cmos_mem_address) {
|
||||
case 0x00: // seconds
|
||||
case 0x01: // seconds alarm
|
||||
case 0x02: // minutes
|
||||
case 0x03: // minutes alarm
|
||||
case 0x04: // hours
|
||||
case 0x05: // hours alarm
|
||||
case 0x06: // day of the week
|
||||
case 0x07: // day of the month
|
||||
case 0x08: // month
|
||||
case 0x09: // year
|
||||
case 0x32: // century (IBM)
|
||||
case 0x37: // century (IBM PS/2)
|
||||
case REG_SEC: // seconds
|
||||
case REG_SEC_ALARM: // seconds alarm
|
||||
case REG_MIN: // minutes
|
||||
case REG_MIN_ALARM: // minutes alarm
|
||||
case REG_HOUR: // hours
|
||||
case REG_HOUR_ALARM: // hours alarm
|
||||
case REG_WEEK_DAY: // day of the week
|
||||
case REG_MONTH_DAY: // day of the month
|
||||
case REG_MONTH: // month
|
||||
case REG_YEAR: // year
|
||||
case REG_IBM_CENTURY_BYTE: // century
|
||||
case REG_IBM_PS2_CENTURY_BYTE: // century (PS/2)
|
||||
//BX_INFO(("write reg 0x%02x: value = 0x%02x",
|
||||
// (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value);
|
||||
BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
|
||||
@ -341,7 +367,7 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x0a: // Control Register A
|
||||
case REG_STAT_A: // Control Register A
|
||||
// bit 7: Update in Progress (read-only)
|
||||
// 1 = signifies time registers will be updated within 244us
|
||||
// 0 = time registers will not occur before 244us
|
||||
@ -378,12 +404,12 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
if (dcc != 0x02) {
|
||||
BX_PANIC(("CRA: divider chain control 0x%02x", dcc));
|
||||
}
|
||||
BX_CMOS_THIS s.reg[0x0a] = value & 0x7f;
|
||||
BX_CMOS_THIS s.reg[REG_STAT_A] = value & 0x7f;
|
||||
BX_CMOS_THIS CRA_change();
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x0b: // Control Register B
|
||||
case REG_STAT_B: // Control Register B
|
||||
// bit 0: Daylight Savings Enable
|
||||
// 1 = enable daylight savings
|
||||
// 0 = disable daylight savings
|
||||
@ -421,8 +447,8 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
value &= 0xef;
|
||||
|
||||
unsigned prev_CRB;
|
||||
prev_CRB = BX_CMOS_THIS s.reg[0x0b];
|
||||
BX_CMOS_THIS s.reg[0x0b] = value;
|
||||
prev_CRB = BX_CMOS_THIS s.reg[REG_STAT_B];
|
||||
BX_CMOS_THIS s.reg[REG_STAT_B] = value;
|
||||
if ( (prev_CRB & 0x40) != (value & 0x40) ) {
|
||||
// Periodic Interrupt Enabled changed
|
||||
if (prev_CRB & 0x40) {
|
||||
@ -433,7 +459,7 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
else {
|
||||
// transition from 0 to 1
|
||||
// if rate select is not 0, activate timer
|
||||
if ( (BX_CMOS_THIS s.reg[0x0a] & 0x0f) != 0 ) {
|
||||
if ( (BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f) != 0 ) {
|
||||
bx_pc_system.activate_timer(
|
||||
BX_CMOS_THIS s.periodic_timer_index,
|
||||
BX_CMOS_THIS s.periodic_interval_usec, 1);
|
||||
@ -443,17 +469,17 @@ bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0x0c: // Control Register C
|
||||
case 0x0d: // Control Register D
|
||||
case REG_STAT_C: // Control Register C
|
||||
case REG_STAT_D: // Control Register D
|
||||
BX_ERROR(("write to control register 0x%02x (read-only)",
|
||||
BX_CMOS_THIS s.cmos_mem_address));
|
||||
break;
|
||||
|
||||
case 0x0e: // diagnostic status
|
||||
case REG_DIAGNOSTIC_STATUS:
|
||||
BX_DEBUG(("write register 0x0e: 0x%02x", (unsigned) value));;
|
||||
break;
|
||||
|
||||
case 0x0f: // shutdown status
|
||||
case REG_SHUTDOWN_STATUS:
|
||||
switch (value) {
|
||||
case 0x00: /* proceed with normal POST (soft reset) */
|
||||
BX_DEBUG(("Reg 0Fh(00): shutdown action = normal POST"));;
|
||||
@ -534,8 +560,8 @@ bx_cmos_c::checksum_cmos(void)
|
||||
for (i=0x10; i<=0x2d; i++) {
|
||||
sum += BX_CMOS_THIS s.reg[i];
|
||||
}
|
||||
BX_CMOS_THIS s.reg[0x2e] = (sum >> 8) & 0xff; /* checksum high */
|
||||
BX_CMOS_THIS s.reg[0x2f] = (sum & 0xff); /* checksum low */
|
||||
BX_CMOS_THIS s.reg[REG_CSUM_HIGH] = (sum >> 8) & 0xff; /* checksum high */
|
||||
BX_CMOS_THIS s.reg[REG_CSUM_LOW] = (sum & 0xff); /* checksum low */
|
||||
}
|
||||
|
||||
void
|
||||
@ -551,8 +577,8 @@ bx_cmos_c::periodic_timer()
|
||||
{
|
||||
// if periodic interrupts are enabled, trip IRQ 8, and
|
||||
// update status register C
|
||||
if (BX_CMOS_THIS s.reg[0x0b] & 0x40) {
|
||||
BX_CMOS_THIS s.reg[0x0c] |= 0xc0; // Interrupt Request, Periodic Int
|
||||
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) {
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xc0; // Interrupt Request, Periodic Int
|
||||
DEV_pic_raise_irq(8);
|
||||
}
|
||||
}
|
||||
@ -573,39 +599,39 @@ bx_cmos_c::one_second_timer()
|
||||
|
||||
// Dont update CMOS user copy of time/date if CRB bit7 is 1
|
||||
// Nothing else do to
|
||||
if (BX_CMOS_THIS s.reg[0x0b] & 0x80)
|
||||
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80)
|
||||
return;
|
||||
|
||||
update_clock();
|
||||
|
||||
// if update interrupts are enabled, trip IRQ 8, and
|
||||
// update status register C
|
||||
if (BX_CMOS_THIS s.reg[0x0b] & 0x10) {
|
||||
BX_CMOS_THIS s.reg[0x0c] |= 0x90; // Interrupt Request, Update Ended
|
||||
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x10) {
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0x90; // Interrupt Request, Update Ended
|
||||
DEV_pic_raise_irq(8);
|
||||
}
|
||||
|
||||
// compare CMOS user copy of time/date to alarm time/date here
|
||||
if (BX_CMOS_THIS s.reg[0x0b] & 0x20) {
|
||||
if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x20) {
|
||||
// Alarm interrupts enabled
|
||||
bx_bool alarm_match = 1;
|
||||
if ( (BX_CMOS_THIS s.reg[0x01] & 0xc0) != 0xc0 ) {
|
||||
if ( (BX_CMOS_THIS s.reg[REG_SEC_ALARM] & 0xc0) != 0xc0 ) {
|
||||
// seconds alarm not in dont care mode
|
||||
if (BX_CMOS_THIS s.reg[0x00] != BX_CMOS_THIS s.reg[0x01])
|
||||
if (BX_CMOS_THIS s.reg[REG_SEC] != BX_CMOS_THIS s.reg[REG_SEC_ALARM])
|
||||
alarm_match = 0;
|
||||
}
|
||||
if ( (BX_CMOS_THIS s.reg[0x03] & 0xc0) != 0xc0 ) {
|
||||
if ( (BX_CMOS_THIS s.reg[REG_MIN_ALARM] & 0xc0) != 0xc0 ) {
|
||||
// minutes alarm not in dont care mode
|
||||
if (BX_CMOS_THIS s.reg[0x02] != BX_CMOS_THIS s.reg[0x03])
|
||||
if (BX_CMOS_THIS s.reg[REG_MIN] != BX_CMOS_THIS s.reg[REG_MIN_ALARM])
|
||||
alarm_match = 0;
|
||||
}
|
||||
if ( (BX_CMOS_THIS s.reg[0x05] & 0xc0) != 0xc0 ) {
|
||||
if ( (BX_CMOS_THIS s.reg[REG_HOUR_ALARM] & 0xc0) != 0xc0 ) {
|
||||
// hours alarm not in dont care mode
|
||||
if (BX_CMOS_THIS s.reg[0x04] != BX_CMOS_THIS s.reg[0x05])
|
||||
if (BX_CMOS_THIS s.reg[REG_HOUR] != BX_CMOS_THIS s.reg[REG_HOUR_ALARM])
|
||||
alarm_match = 0;
|
||||
}
|
||||
if (alarm_match) {
|
||||
BX_CMOS_THIS s.reg[0x0c] |= 0xa0; // Interrupt Request, Alarm Int
|
||||
BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xa0; // Interrupt Request, Alarm Int
|
||||
DEV_pic_raise_irq(8);
|
||||
}
|
||||
}
|
||||
@ -625,41 +651,43 @@ bx_cmos_c::update_clock()
|
||||
val_bcd =
|
||||
((time_calendar->tm_sec / 10) << 4) |
|
||||
(time_calendar->tm_sec % 10);
|
||||
BX_CMOS_THIS s.reg[0x00] = val_bcd;
|
||||
BX_CMOS_THIS s.reg[REG_SEC] = val_bcd;
|
||||
|
||||
// update minutes
|
||||
val_bcd =
|
||||
((time_calendar->tm_min / 10) << 4) |
|
||||
(time_calendar->tm_min % 10);
|
||||
BX_CMOS_THIS s.reg[0x02] = val_bcd;
|
||||
BX_CMOS_THIS s.reg[REG_MIN] = val_bcd;
|
||||
|
||||
// update hours
|
||||
val_bcd =
|
||||
((time_calendar->tm_hour / 10) << 4) |
|
||||
(time_calendar->tm_hour % 10);
|
||||
BX_CMOS_THIS s.reg[0x04] = val_bcd;
|
||||
BX_CMOS_THIS s.reg[REG_HOUR] = val_bcd;
|
||||
|
||||
// update day of the week
|
||||
day = time_calendar->tm_wday + 1; // 0..6 to 1..7
|
||||
BX_CMOS_THIS s.reg[0x06] = ((day / 10) << 4) | (day % 10);
|
||||
BX_CMOS_THIS s.reg[REG_WEEK_DAY] = ((day / 10) << 4) | (day % 10);
|
||||
|
||||
// update day of the month
|
||||
day = time_calendar->tm_mday;
|
||||
BX_CMOS_THIS s.reg[0x07] = ((day / 10) << 4) | (day % 10);
|
||||
BX_CMOS_THIS s.reg[REG_MONTH_DAY] = ((day / 10) << 4) | (day % 10);
|
||||
|
||||
// update month
|
||||
month = time_calendar->tm_mon + 1;
|
||||
BX_CMOS_THIS s.reg[0x08] = ((month / 10) << 4) | (month % 10);
|
||||
BX_CMOS_THIS s.reg[REG_MONTH] = ((month / 10) << 4) | (month % 10);
|
||||
|
||||
// update year
|
||||
year = time_calendar->tm_year % 100;
|
||||
BX_CMOS_THIS s.reg[0x09] = ((year / 10) << 4) | (year % 10);
|
||||
BX_CMOS_THIS s.reg[REG_YEAR] = ((year / 10) << 4) | (year % 10);
|
||||
|
||||
// update century
|
||||
century = (time_calendar->tm_year / 100) + 19;
|
||||
BX_CMOS_THIS s.reg[0x32] = ((century / 10) << 4) | (century % 10);
|
||||
BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] =
|
||||
((century / 10) << 4) | (century % 10);
|
||||
|
||||
// Raul Hudea pointed out that some bioses also use reg 0x37 for the century
|
||||
// byte. Tony Heller says this is critical in getting WinXP to run.
|
||||
BX_CMOS_THIS s.reg[0x37] = BX_CMOS_THIS s.reg[0x32];
|
||||
// Raul Hudea pointed out that some bioses also use reg 0x37 for the
|
||||
// century byte. Tony Heller says this is critical in getting WinXP to run.
|
||||
BX_CMOS_THIS s.reg[REG_IBM_PS2_CENTURY_BYTE] =
|
||||
BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user