1
0
Fork 0

Add checking if an irq needs to be raised immediatly when programming new timer

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1945
This commit is contained in:
Sjoerd van der Berg 2004-09-07 11:28:27 +00:00
parent 10d9e724d9
commit d94017a7b1

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: timer.cpp,v 1.27 2004-08-31 15:56:10 harekiet Exp $ */
/* $Id: timer.cpp,v 1.28 2004-09-07 11:28:27 harekiet Exp $ */
#include "dosbox.h"
#include "inout.h"
@ -37,7 +37,6 @@ static INLINE void BCD2BIN(Bit16u& val) {
val=temp;
}
static bool pit0_scheduled;
struct PIT_Block {
Bit8u mode; /* Current Counter Mode */
@ -52,15 +51,37 @@ struct PIT_Block {
Bit16u write_latch;
bool bcd;
bool go_read_latch;
bool new_mode;
};
static PIT_Block pit[3];
static void PIT0_Event(Bitu val) {
PIC_ActivateIRQ(0);
if (pit[0].mode!=0) {
PIC_AddEvent(PIT0_Event,pit[0].micro);
} else pit0_scheduled=false;
if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].micro);
}
static bool counter_output(Bitu counter) {
PIT_Block * p=&pit[counter];
Bit64s micro=PIC_MicroCount()-p->start;
switch (p->mode) {
case 0:
if (p->new_mode) return false;
if (micro>p->micro) return true;
else return false;
break;
case 2:
if (p->new_mode) return true;
micro%=p->micro;
return micro>0;
case 3:
if (p->new_mode) return true;
micro%=p->micro;
return micro*2<p->micro;
default:
LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode);
return true;
}
}
static void counter_latch(Bitu counter) {
@ -69,7 +90,6 @@ static void counter_latch(Bitu counter) {
p->go_read_latch=false;
Bit64s micro=PIC_MicroCount()-p->start;
switch (p->mode) {
case 0: /* Interrupt on Terminal Count */
/* Counter keeps on counting after passing terminal count */
@ -136,11 +156,10 @@ static void write_latch(Bitu port,Bitu val,Bitu iolen) {
if (!p->micro) p->micro=1;
switch (counter) {
case 0x00: /* Timer hooked to IRQ 0 */
if (!p->mode || !pit0_scheduled) {
pit0_scheduled=true;
PIC_RemoveEvents(PIT0_Event);
if (p->new_mode) {
p->new_mode=false;
PIC_AddEvent(PIT0_Event,p->micro);
}
} else LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer set without new control word");
LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,(Bit32u)p->mode);
break;
case 0x02: /* Timer hooked to PC-Speaker */
@ -207,6 +226,14 @@ static void write_p43(Bitu port,Bitu val,Bitu iolen) {
pit[latch].read_state = (val >> 4) & 0x03;
pit[latch].write_state = (val >> 4) & 0x03;
pit[latch].mode = (val >> 1) & 0x07;
if (pit[latch].mode>5)
pit[latch].mode-=4; //6,7 become 2 and 3
if (latch==0) {
PIC_RemoveEvents(PIT0_Event);
if (!counter_output(0) && pit[latch].mode)
PIC_ActivateIRQ(0);
}
pit[latch].new_mode = true;
}
break;
case 3:
@ -260,7 +287,6 @@ void TIMER_Init(Section* sect) {
pit[1].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[1].cntr));
pit[2].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[2].cntr));
pit0_scheduled=true;
PIC_AddEvent(PIT0_Event,pit[0].micro);
}