0

First, I program for Vintage computer groups. What I write is specifically for MS-DOS and not windows, because that's what people are running. My current program is for later systems and not the 8086 line, so the plan was to use IRQ 8. This allows me to set the interrupt rate in binary values from 2 / second to 8192 / second (2, 4, 8, 16, etc...)

Only, for some reason, on the newer old systems (ok, that sounds weird,) it doesn't seem to be working. In emulation, and the 386 system I have access to, it works just fine, but on the P3 system I have (GA-6BXC MB w/P3 800 CPU,) it just doesn't work.

The code

setting up the interrupt

disable();
oldrtc = getvect(0x70);    //Reads the vector for IRQ 8
settvect(0x70,countdown);  //Sets the vector for

outportb(0x70,0x8a);
y = inportb(0x71) & 0xf0;
outportb(0x70,0x8a);
outportb(0x71,y | _MRATE_); //Adjustable value, set for 64 interrupts per second

outportb(0x70,0x8b);
y = inportb(0x71);
outportb(0x70,0x8b);
outportb(0x71,y | 0x40);

enable();

at the end of the interrupt

outportb(0x70,0x0c);
inportb(0x71);        //Reading the C register resets the interrupt
outportb(0xa0,0x20);  //Resets the PIC (turns interrupts back on)
outportb(0x20,0x20);  //There are 2 PICs on AT machines and later

When closing program down

disable();

outportb(0x70,0x8b);
y = inportb(0x71);
outportb(0x70,0x8b);
outportb(0x71,y & 0xbf);
setvect(0x70,oldrtc);

enable();

I don't see anything in the code that can be causing the problem. But it just doesn't seem to make sense. While I don't completely trust the information, MSD "does" report IRQ 8 as the RTC Counter and says it is present and working just fine. Is it possible that later systems have moved the vector? Everything I find says that IRQ 8 is vector 0x70, but the interrupt never triggers on my Pentium III system. Is there some way to find if the Vectors have been changed?

user3399848
  • 125
  • 7

1 Answers1

1

It's been a LONG time since I've done any MS-DOS code and I don't think I ever worked with this particular interrupt (I'm pretty sure you can just read the memory location to fetch the time too, and IRQ0 can be used to trigger you at an interval too, so maybe that's better. Anyway, given my rustiness, forgive me for kinda link dumping.

http://wiki.osdev.org/Real_Time_Clock the bottom of that page has someone saying they've had problem on some machines too. RBIL suggests it might be a BIOS thing: http://www.ctyme.com/intr/rb-7797.htm

Without DOS, I'd just capture IRQ0 itself and remap all of them to my own interrupt numbers and change the timing as needed. I've done that somewhat recently! I think that's a bad idea on DOS though, this looks more recommended for that: http://www.ctyme.com/intr/rb-2443.htm

Anyway though, I betcha it has to do with the BIOS thing:

"Notes: Many BIOSes turn off the periodic interrupt in the INT 70h handler unless in an event wait (see INT 15/AH=83h,INT 15/AH=86h).. May be masked by setting bit 0 on I/O port A1h "

Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • I'm actually already using PIT1 & PIT3 for extremely fast (short code,) functions. In my first build, I also used it for the timer functions, but that code does more (and thus needs a larger amount of code.) This led to extreme performance degradation. Code running 64 times a second has less of an impact than code hitting 23K times per second. And yes, I'm already adjusting the clock for the faster PIT1 interrupt routine. I'm discouraged to discover that the BIOS could be totally disabling IRQ 8. I can't seem to find a way to detect this & re-enable it :( – user3399848 Nov 25 '14 at 21:40
  • Discovered that some BIOS types will mask IRQ 8. So I added the lines outportb(0xa1,inportb(0xa1) & 0x7f); outportb(0x21,inportb(0x21) & 0xdf); to the initialization. But it didn't solve the issue. – user3399848 Nov 25 '14 at 22:26
  • Hmm, I can't think of anything else to try. Another workaround that comes in through is putting a ticker in your short event handler and only when it rolls over do you run the other one. So it throttles the call to the slower function. So like in the 23k/sec function, `inc [somebyte]; jz do_more; iret;` - when somebyte rolls back to 0, it means you've gone 256 iterations and can call it again. That'd work out to like 90 calls per second without being horribly slow on the times when it doesn't call it. – Adam D. Ruppe Nov 25 '14 at 22:37
  • Ok, my very bad... Had the bit masks backwards. Changed it to: `outportb(0xa1,inportb(0xa1) & 0xfe);` `outportb(0x21,inportb(0x21) & 0xfb);` and now it's working just fine(ish) Still getting the timings corrected, but that's a code tweak issue that isn't related to this – user3399848 Nov 25 '14 at 22:45
  • yikes, I eyeballed your code to check that too and I made the same mistake you did! But this is good to hear! – Adam D. Ruppe Nov 25 '14 at 22:48
  • I highly doubt the second part of that (port 0x21) is necessary (it turns on IRQ 2 which is the cascade to PIC2.) But, I figure it doesn't hurt :) – user3399848 Nov 25 '14 at 22:57