I've got a problem with getting RTC to cooperate. First of all, when I read CMOS values for minutes and hours it returns weird values. For example, minutes seem to be in the range of 0-100, and hours are quite random and also extend 24 hours. So I get times like 32:72, which is quite weird. This problem occurs on both bochs and quemu, although values differ a little bit from one emulator to another.
My second problem is that I try to enable RTC interrupts but they do not occur.
The code I use is below, can you spot, a problem in it?
Code: Select all
void RTC_init()
{
uint8_t m;
uint8_t h;
bool update_in_progress;
disable_interrupts();
// Read from CMOS
// may take up to 1 second, prevents from reading dodgy data for example minute: 60
outb(0x70, (1 << 7) | (0x0A));
update_in_progress = ((inb(0x71) << 1) >> 7);
while(!update_in_progress)
{
outb(0x70, (1 << 7) | (0x0A));
update_in_progress = ((inb(0x71) << 1) >> 7);
}
outb(0x70, (1 << 7) | (0x0A));
update_in_progress = ((inb(0x71) << 1) >> 7);
while(update_in_progress)
{
outb(0x70, (1 << 7) | (0x0A));
update_in_progress = ((inb(0x71) << 1) >> 7);
}
outb(0x70, (1 << 7) | (0x02));
io_wait();
m = inb (0x71);
outb(0x70, (1 << 7) | (0x04));
io_wait();
h = inb (0x71);
// Enable RTC interrupts
int rate = 14;
rate &= 0x0F; // rate must be above 2 and not over 15
outb(0x70, (1 << 7) | (0x0A)); // set index to register A, disable NMI
uint8_t prev = inb(0x71); // get initial value of register A
outb(0x70, (1 << 7) | (0x0A)); // reset index to A
outb(0x71, (prev & 0xF0) | rate); //write only our rate to A. Note, rate is the bottom 4 bits.
outb(0x70, (1 << 7) | (0x0B));
prev = inb(0x71);
outb(0x70, (1 << 7) | (0x0B));
outb(0x71, prev | 0x40);
enable_interrupts();
enable_RTC_irq();
outb(0x70, 0x0C); // select register C
inb(0x71); // just throw away contents
RTCminute = (int)m;
RTChour = (int)h;
terminal_print(debugTerminal, "RTC ready, time: %d:%d\n", RTChour, RTCminute);
}