Hi,
Candamir wrote:Why would I want to keep the three top bits? If only the last five are taken into account, why should I preserve them?
The highest bit of I/O port 0x70 usually enables/disables the NMI.
This means if you've disabled the NMI for some reason by setting the highest bit (out 0x70,0x80) then you'd want to preserve this bit when you're accessing CMOS locations.
Bits 0 to 6 are normally used to select the CMOS location (for up to 128 bytes of CMOS) and shouldn't be preserved.
This implies something like:
Code: Select all
outb(0x70, ( (inb(0x70) & 0x80) | (cmos_register & 0x7F) ) );
The problem here is that I/O port accesses to "legacy" devices (anything on the "PCI to LPC bridge") is slow - it doesn't make sense to read the previous value just to find out if NMI is enabled or disabled when you should already know.
Basically, if you disable IRQs when you disable NMI and if you don't access CMOS when NMI is disabled, then you know the NMI bit will always be enabled for normal code and it'd be faster to do something like this:
Code: Select all
outb(0x70, (cmos_register & 0x7F) );
This should work fine as there's normally no reason to disable the NMI (it's actually not meant to be maskable in the first place).
I guess I should also point out that the NMI enable/disable bit only controls the motherboard's "hardware failure" NMI. It's possible to do some unusual things (like setting a timer IRQ as an NMI in the I/O APIC) where I/O port 0x70 has no effect on your "timer NMI".
This might sound insane, but there's actually good reasons for doing this. One reason is using it as a watchdog timer to find out if the computer has locked up. For e.g. if someone does "cli; hlt" then the timer IRQ will still work and can recover (terminate the malicious driver??). The other reason is for profiling - keep track of what EIP was when the timer interrupted to see where the CPU is spending it's time. Using an NMI in this case means you get correct "profiling statistics" regardless of whether IRQs are enabled or not.
Cheers,
Brendan