diff options
Diffstat (limited to 'tools/ioemu/iodev/pit82c54.cc')
-rw-r--r-- | tools/ioemu/iodev/pit82c54.cc | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/tools/ioemu/iodev/pit82c54.cc b/tools/ioemu/iodev/pit82c54.cc new file mode 100644 index 0000000000..fc913b1334 --- /dev/null +++ b/tools/ioemu/iodev/pit82c54.cc @@ -0,0 +1,893 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: pit82c54.cc,v 1.23 2003/06/29 17:24:52 vruppert Exp $ +///////////////////////////////////////////////////////////////////////// +// +/* + * Emulator of an Intel 8254/82C54 Programmable Interval Timer. + * Greg Alexander <yakovlev@usa.com> + * + * + * Things I am unclear on (greg): + * 1.)What happens if both the status and count registers are latched, + * but the first of the two count registers has already been read? + * I.E.: + * latch count 0 (16-bit) + * Read count 0 (read LSByte) + * READ_BACK status of count 0 + * Read count 0 - do you get MSByte or status? + * This will be flagged as an error. + * 2.)What happens when we latch the output in the middle of a 2-part + * unlatched read? + * 3.)I assumed that programming a counter removes a latched status. + * 4.)I implemented the 8254 description of mode 0, not the 82C54 one. + * 5.)clock() calls represent a rising clock edge followed by a falling + * clock edge. + * 6.)What happens when we trigger mode 1 in the middle of a 2-part + * write? + */ + +#include "bochs.h" +#include "pit82c54.h" +#define LOG_THIS this-> + + +void pit_82C54::print_counter(counter_type & thisctr) { +#if 1 + BX_INFO(("Printing Counter")); + BX_INFO(("count: %d",thisctr.count)); + BX_INFO(("count_binary: %x",thisctr.count_binary)); + BX_INFO(("counter gate: %x",thisctr.GATE)); + BX_INFO(("counter OUT: %x",thisctr.OUTpin)); + BX_INFO(("next_change_time: %d",thisctr.next_change_time)); + BX_INFO(("End Counter Printout")); +#endif +} + +void pit_82C54::print_cnum(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Bad counter index to print_cnum")); + } else { + print_counter(counter[cnum]); + } +} + + void pit_82C54::latch_counter(counter_type & thisctr) { + if(thisctr.count_LSB_latched || thisctr.count_MSB_latched) { + //Do nothing because previous latch has not been read.; + } else { + switch(thisctr.read_state) { + case MSByte: + thisctr.outlatch=thisctr.count & 0xFFFF; + thisctr.count_MSB_latched=1; + break; + case LSByte: + thisctr.outlatch=thisctr.count & 0xFFFF; + thisctr.count_LSB_latched=1; + break; + case LSByte_multiple: + thisctr.outlatch=thisctr.count & 0xFFFF; + thisctr.count_LSB_latched=1; + thisctr.count_MSB_latched=1; + break; + case MSByte_multiple: + if(!(seen_problems & UNL_2P_READ)) { +// seen_problems|=UNL_2P_READ; + BX_ERROR(("Unknown behavior when latching during 2-part read.")); + BX_ERROR((" This message will not be repeated.")); + } + //I guess latching and resetting to LSB first makes sense; + BX_DEBUG(("Setting read_state to LSB_mult")); + thisctr.read_state=LSByte_multiple; + thisctr.outlatch=thisctr.count & 0xFFFF; + thisctr.count_LSB_latched=1; + thisctr.count_MSB_latched=1; + break; + default: + BX_ERROR(("Unknown read mode found during latch command.")); + break; + } + } + } + + void pit_82C54::set_OUT (counter_type & thisctr, bool data) { + //This will probably have a callback, so I put it here. + thisctr.OUTpin=data; + } + + void BX_CPP_AttrRegparmN(2) +pit_82C54::set_count (counter_type & thisctr, Bit32u data) { + thisctr.count=data & 0xFFFF; + set_binary_to_count(thisctr); + } + + void BX_CPP_AttrRegparmN(1) +pit_82C54::set_count_to_binary(counter_type & thisctr) { + if(thisctr.bcd_mode) { + thisctr.count= + (((thisctr.count_binary/1)%10)<<0) | + (((thisctr.count_binary/10)%10)<<4) | + (((thisctr.count_binary/100)%10)<<8) | + (((thisctr.count_binary/1000)%10)<<12) + ; + } else { + thisctr.count=thisctr.count_binary; + } + } + + void BX_CPP_AttrRegparmN(1) +pit_82C54::set_binary_to_count(counter_type & thisctr) { + if(thisctr.bcd_mode) { + thisctr.count_binary= + (1*((thisctr.count>>0)&0xF)) + + (10*((thisctr.count>>4)&0xF)) + + (100*((thisctr.count>>8)&0xF)) + + (1000*((thisctr.count>>12)&0xF)) + ; + } else { + thisctr.count_binary=thisctr.count; + } + } + + void BX_CPP_AttrRegparmN(1) +pit_82C54::decrement (counter_type & thisctr) { + if(!thisctr.count) { + if(thisctr.bcd_mode) { + thisctr.count=0x9999; + thisctr.count_binary=9999; + } else { + thisctr.count=0xFFFF; + thisctr.count_binary=0xFFFF; + } + } else { + thisctr.count_binary--; + set_count_to_binary(thisctr); + } + } + + void pit_82C54::init (void) { + Bit8u i; + + put("PIT81"); + settype(PIT81LOG); + + for(i=0;i<3;i++) { + BX_DEBUG(("Setting read_state to LSB")); + counter[i].read_state=LSByte; + counter[i].write_state=LSByte; + counter[i].GATE=1; + counter[i].OUTpin=1; + counter[i].triggerGATE=0; + counter[i].mode=4; + counter[i].first_pass=0; + counter[i].bcd_mode=0; + counter[i].count=0; + counter[i].count_binary=0; + counter[i].state_bit_1=0; + counter[i].state_bit_2=0; + counter[i].null_count=0; + counter[i].rw_mode=1; + counter[i].count_written=1; + counter[i].count_LSB_latched=0; + counter[i].count_MSB_latched=0; + counter[i].status_latched=0; + counter[i].next_change_time=0; + } + seen_problems=0; + } + + pit_82C54::pit_82C54 (void) { + init(); + } + + void pit_82C54::reset (unsigned type) { + } + +void BX_CPP_AttrRegparmN(2) +pit_82C54::decrement_multiple(counter_type & thisctr, Bit32u cycles) { + while(cycles>0) { + if(cycles<=thisctr.count_binary) { + thisctr.count_binary-=cycles; + cycles-=cycles; + set_count_to_binary(thisctr); + } else { + cycles-=(thisctr.count_binary+1); + thisctr.count_binary-=thisctr.count_binary; + set_count_to_binary(thisctr); + decrement(thisctr); + } + } +} + +void pit_82C54::clock_multiple(Bit8u cnum, Bit32u cycles) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number too high in clock")); + } else { + counter_type & thisctr = counter[cnum]; + while(cycles>0) { + if(thisctr.next_change_time==0) { + if(thisctr.count_written) { + switch(thisctr.mode) { + case 0: + if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { + decrement_multiple(thisctr, cycles); + } + break; + case 1: + decrement_multiple(thisctr, cycles); + break; + case 2: + if( (!thisctr.first_pass) && thisctr.GATE ) { + decrement_multiple(thisctr, cycles); + } + break; + case 3: + if( (!thisctr.first_pass) && thisctr.GATE ) { + decrement_multiple(thisctr, 2*cycles); + } + break; + case 4: + if(thisctr.GATE) { + decrement_multiple(thisctr, cycles); + } + break; + case 5: + decrement_multiple(thisctr, cycles); + break; + default: + break; + } + } + cycles-=cycles; + } else { + switch(thisctr.mode) { + case 0: + case 1: + case 2: + case 4: + case 5: + if( thisctr.next_change_time > cycles ) { + decrement_multiple(thisctr,cycles); + thisctr.next_change_time-=cycles; + cycles-=cycles; + } else { + decrement_multiple(thisctr,(thisctr.next_change_time-1)); + cycles-=thisctr.next_change_time; + clock(cnum); + } + break; + case 3: + if( thisctr.next_change_time > cycles ) { + decrement_multiple(thisctr,cycles*2); + thisctr.next_change_time-=cycles; + cycles-=cycles; + } else { + decrement_multiple(thisctr,(thisctr.next_change_time-1)*2); + cycles-=thisctr.next_change_time; + clock(cnum); + } + break; + default: + cycles-=cycles; + break; + } + } + } +#if 0 + print_counter(thisctr); +#endif + } +} + + void BX_CPP_AttrRegparmN(1) +pit_82C54::clock(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number too high in clock")); + } else { + counter_type & thisctr = counter[cnum]; + switch(thisctr.mode) { + case 0: + if(thisctr.count_written) { + if(thisctr.null_count) { + set_count(thisctr, thisctr.inlatch); + if(thisctr.GATE) { + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + } else { + thisctr.next_change_time=0; + } + thisctr.null_count=0; + } else { + if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { + decrement(thisctr); + if(!thisctr.OUTpin) { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + if(!thisctr.count) { + set_OUT(thisctr,1); + } + } else { + thisctr.next_change_time=0; + } + } else { + thisctr.next_change_time=0; //if the clock isn't moving. + } + } + } else { + thisctr.next_change_time=0; //default to 0. + } + thisctr.triggerGATE=0; + break; + case 1: + if(thisctr.count_written) { + if(thisctr.triggerGATE) { + set_count(thisctr, thisctr.inlatch); + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + thisctr.null_count=0; + set_OUT(thisctr,0); + if(thisctr.write_state==MSByte_multiple) { + BX_ERROR(("Undefined behavior when loading a half loaded count.")); + } + } else { + decrement(thisctr); + if(!thisctr.OUTpin) { + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + if(thisctr.count==0) { + set_OUT(thisctr,1); + } + } else { + thisctr.next_change_time=0; + } + } + } else { + thisctr.next_change_time=0; //default to 0. + } + thisctr.triggerGATE=0; + break; + case 2: + if(thisctr.count_written) { + if(thisctr.triggerGATE || thisctr.first_pass) { + set_count(thisctr, thisctr.inlatch); + thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; + thisctr.null_count=0; + if(thisctr.inlatch==1) { + BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2.")); + } + if(!thisctr.OUTpin) { + set_OUT(thisctr,1); + } + if(thisctr.write_state==MSByte_multiple) { + BX_ERROR(("Undefined behavior when loading a half loaded count.")); + } + thisctr.first_pass=0; + } else { + if(thisctr.GATE) { + decrement(thisctr); + thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; + if(thisctr.count==1) { + thisctr.next_change_time=1; + set_OUT(thisctr,0); + thisctr.first_pass=1; + } + } else { + thisctr.next_change_time=0; + } + } + } else { + thisctr.next_change_time=0; + } + thisctr.triggerGATE=0; + break; + case 3: + if(thisctr.count_written) { + if( (thisctr.triggerGATE || thisctr.first_pass + || thisctr.state_bit_2) && thisctr.GATE ) { + set_count(thisctr, thisctr.inlatch & 0xFFFE); + thisctr.state_bit_1=thisctr.inlatch & 0x1; + if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) { + if(((thisctr.count_binary/2)-1)==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; + } + } else { + if((thisctr.count_binary/2)==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; + } + } + thisctr.null_count=0; + if(thisctr.inlatch==1) { + BX_ERROR(("Count of 1 is invalid in pit mode 3.")); + } + if(!thisctr.OUTpin) { + set_OUT(thisctr,1); + } else if(thisctr.OUTpin && !thisctr.first_pass) { + set_OUT(thisctr,0); + } + if(thisctr.write_state==MSByte_multiple) { + BX_ERROR(("Undefined behavior when loading a half loaded count.")); + } + thisctr.state_bit_2=0; + thisctr.first_pass=0; + } else { + if(thisctr.GATE) { + decrement(thisctr); + decrement(thisctr); + if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) { + thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; + } else { + thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; + } + if(thisctr.count==0) { + thisctr.state_bit_2=1; + thisctr.next_change_time=1; + } + if( (thisctr.count==2) && + ( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) + ) { + thisctr.state_bit_2=1; + thisctr.next_change_time=1; + } + } else { + thisctr.next_change_time=0; + } + } + } else { + thisctr.next_change_time=0; + } + thisctr.triggerGATE=0; + break; + case 4: + if(thisctr.count_written) { + if(!thisctr.OUTpin) { + set_OUT(thisctr,1); + } + if(thisctr.null_count) { + set_count(thisctr, thisctr.inlatch); + if(thisctr.GATE) { + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + } else { + thisctr.next_change_time=0; + } + thisctr.null_count=0; + if(thisctr.write_state==MSByte_multiple) { + BX_ERROR(("Undefined behavior when loading a half loaded count.")); + } + thisctr.first_pass=1; + } else { + if(thisctr.GATE) { + decrement(thisctr); + if(thisctr.first_pass) { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + if(!thisctr.count) { + set_OUT(thisctr,0); + thisctr.next_change_time=1; + thisctr.first_pass=0; + } + } else { + thisctr.next_change_time=0; + } + } else { + thisctr.next_change_time=0; + } + } + } else { + thisctr.next_change_time=0; + } + thisctr.triggerGATE=0; + break; + case 5: + if(thisctr.count_written) { + if(!thisctr.OUTpin) { + set_OUT(thisctr,1); + } + if(thisctr.triggerGATE) { + set_count(thisctr, thisctr.inlatch); + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + thisctr.null_count=0; + if(thisctr.write_state==MSByte_multiple) { + BX_ERROR(("Undefined behavior when loading a half loaded count.")); + } + thisctr.first_pass=1; + } else { + decrement(thisctr); + if(thisctr.first_pass) { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + if(!thisctr.count) { + set_OUT(thisctr,0); + thisctr.next_change_time=1; + thisctr.first_pass=0; + } + } else { + thisctr.next_change_time=0; + } + } + } else { + thisctr.next_change_time=0; + } + thisctr.triggerGATE=0; + break; + default: + BX_ERROR(("Mode not implemented.")); + thisctr.next_change_time=0; + thisctr.triggerGATE=0; + break; + } + } + } + + void pit_82C54::clock_all(Bit32u cycles) { + BX_DEBUG(("clock_all: cycles=%d",cycles)); + clock_multiple(0,cycles); + clock_multiple(1,cycles); + clock_multiple(2,cycles); + } + + Bit8u pit_82C54::read(Bit8u address) { + if(address>MAX_ADDRESS) { + BX_ERROR(("Counter address incorrect in data read.")); + } else if(address==CONTROL_ADDRESS) { + BX_DEBUG(("PIT Read: Control Word Register.")); + //Read from control word register; + /* This might be okay. If so, 0 seems the most logical + * return value from looking at the docs. + */ + BX_ERROR(("Read from control word register not defined.")); + return 0; + } else { + //Read from a counter; + BX_DEBUG(("PIT Read: Counter %d.",address)); + counter_type & thisctr=counter[address]; + if(thisctr.status_latched) { + //Latched Status Read; + if(thisctr.count_MSB_latched && + (thisctr.read_state==MSByte_multiple) ) { + BX_ERROR(("Undefined output when status latched and count half read.")); + } else { + thisctr.status_latched=0; + return thisctr.status_latch; + } + } else { + //Latched Count Read; + if(thisctr.count_LSB_latched) { + //Read Least Significant Byte; + if(thisctr.read_state==LSByte_multiple) { + BX_DEBUG(("Setting read_state to MSB_mult")); + thisctr.read_state=MSByte_multiple; + } + thisctr.count_LSB_latched=0; + return (thisctr.outlatch & 0xFF); + } else if(thisctr.count_MSB_latched) { + //Read Most Significant Byte; + if(thisctr.read_state==MSByte_multiple) { + BX_DEBUG(("Setting read_state to LSB_mult")); + thisctr.read_state=LSByte_multiple; + } + thisctr.count_MSB_latched=0; + return ((thisctr.outlatch>>8) & 0xFF); + } else { + //Unlatched Count Read; + if(!(thisctr.read_state & 0x1)) { + //Read Least Significant Byte; + if(thisctr.read_state==LSByte_multiple) { + thisctr.read_state=MSByte_multiple; + BX_DEBUG(("Setting read_state to MSB_mult")); + } + return (thisctr.count & 0xFF); + } else { + //Read Most Significant Byte; + if(thisctr.read_state==MSByte_multiple) { + BX_DEBUG(("Setting read_state to LSB_mult")); + thisctr.read_state=LSByte_multiple; + } + return ((thisctr.count>>8) & 0xFF); + } + } + } + } + //Should only get here on errors; + return 0; + } + + void pit_82C54::write(Bit8u address, Bit8u data) { + if(address>MAX_ADDRESS) { + BX_ERROR(("Counter address incorrect in data write.")); + } else if(address==CONTROL_ADDRESS) { + Bit8u SC, RW, M, BCD; + controlword=data; + BX_DEBUG(("Control Word Write.")); + SC = (controlword>>6) & 0x3; + RW = (controlword>>4) & 0x3; + M = (controlword>>1) & 0x7; + BCD = controlword & 0x1; + if(SC == 3) { + //READ_BACK command; + int i; + BX_DEBUG(("READ_BACK command.")); + for(i=0;i<=MAX_COUNTER;i++) { + if((M>>i) & 0x1) { + //If we are using this counter; + counter_type & thisctr=counter[i]; + if(!((controlword>>5) & 1)) { + //Latch Count; + latch_counter(thisctr); + } + if(!((controlword>>4) & 1)) { + //Latch Status; + if(thisctr.status_latched) { + //Do nothing because latched status has not been read.; + } else { + thisctr.status_latch= + ((thisctr.OUTpin & 0x1) << 7) | + ((thisctr.null_count & 0x1) << 6) | + ((thisctr.rw_mode & 0x3) << 4) | + ((thisctr.mode & 0x7) << 1) | + (thisctr.bcd_mode&0x1) + ; + thisctr.status_latched=1; + } + } + } + } + } else { + counter_type & thisctr = counter[SC]; + if(!RW) { + //Counter Latch command; + BX_DEBUG(("Counter Latch command. SC=%d",SC)); + latch_counter(thisctr); + } else { + //Counter Program Command; + BX_DEBUG(("Counter Program command. SC=%d, RW=%d, M=%d, BCD=%d",SC,RW,M,BCD)); + thisctr.null_count=1; + thisctr.count_LSB_latched=0; + thisctr.count_MSB_latched=0; + thisctr.status_latched=0; + thisctr.inlatch=0; + thisctr.count_written=0; + thisctr.first_pass=1; + thisctr.rw_mode=RW; + thisctr.bcd_mode=(BCD > 0); + thisctr.mode=M; + switch(RW) { + case 0x1: + BX_DEBUG(("Setting read_state to LSB")); + thisctr.read_state=LSByte; + thisctr.write_state=LSByte; + break; + case 0x2: + BX_DEBUG(("Setting read_state to MSB")); + thisctr.read_state=MSByte; + thisctr.write_state=MSByte; + break; + case 0x3: + BX_DEBUG(("Setting read_state to LSB_mult")); + thisctr.read_state=LSByte_multiple; + thisctr.write_state=LSByte_multiple; + break; + default: + BX_ERROR(("RW field invalid in control word write.")); + break; + } + //All modes except mode 0 have initial output of 1.; + if(M) { + set_OUT(thisctr, 1); + } else { + set_OUT(thisctr, 0); + } + thisctr.next_change_time=0; + } + } + } else { + //Write to counter initial value. + counter_type & thisctr = counter[address]; + BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address,data)); + switch(thisctr.write_state) { + case LSByte_multiple: + thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data; + thisctr.write_state=MSByte_multiple; + break; + case LSByte: + thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data; + thisctr.null_count=1; + thisctr.count_written=1; + break; + case MSByte_multiple: + thisctr.write_state=LSByte_multiple; + case MSByte: //shared between MSB_multiple and MSByte + thisctr.inlatch=(thisctr.inlatch & 0xFF) | (data<<8); + thisctr.null_count=1; + thisctr.count_written=1; + break; + default: + BX_ERROR(("write counter in invalid write state.")); + break; + } + switch(thisctr.mode) { + case 0: + if(thisctr.write_state==MSByte_multiple) { + set_OUT(thisctr,0); + } + thisctr.next_change_time=1; + break; + case 1: + if(thisctr.triggerGATE) { //for initial writes, if already saw trigger. + thisctr.next_change_time=1; + } //Otherwise, no change. + break; + case 6: + case 2: + thisctr.next_change_time=1; //FIXME: this could be loosened. + break; + case 7: + case 3: + thisctr.next_change_time=1; //FIXME: this could be loosened. + break; + case 4: + thisctr.next_change_time=1; + break; + case 5: + if(thisctr.triggerGATE) { //for initial writes, if already saw trigger. + thisctr.next_change_time=1; + } //Otherwise, no change. + break; + } + } + } + + void pit_82C54::set_GATE(Bit8u cnum, bool data) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number incorrect in 82C54 set_GATE")); + } else { + counter_type & thisctr = counter[cnum]; + if(!( (thisctr.GATE&&data) || (!(thisctr.GATE||data)) )) { + BX_INFO(("Changing GATE %d to: %d",cnum,data)); + thisctr.GATE=data; + if(thisctr.GATE) { + thisctr.triggerGATE=1; + } + switch(thisctr.mode) { + case 0: + if(data && thisctr.count_written) { + if(thisctr.null_count) { + thisctr.next_change_time=1; + } else { + if( (!thisctr.OUTpin) && + (thisctr.write_state!=MSByte_multiple) + ) { + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + } else { + thisctr.next_change_time=0; + } + } + } else { + if(thisctr.null_count) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=0; + } + } + break; + case 1: + if(data && thisctr.count_written) { //only triggers cause a change. + thisctr.next_change_time=1; + } + break; + case 2: + if(!data) { + set_OUT(thisctr,1); + thisctr.next_change_time=0; + } else { + if(thisctr.count_written) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=0; + } + } + break; + case 3: + if(!data) { + set_OUT(thisctr,1); + thisctr.first_pass=1; + thisctr.next_change_time=0; + } else { + if(thisctr.count_written) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=0; + } + } + break; + case 4: + if(!thisctr.OUTpin || thisctr.null_count) { + thisctr.next_change_time=1; + } else { + if(data && thisctr.count_written) { + if(thisctr.first_pass) { + if(thisctr.count_binary==0) { + thisctr.next_change_time=1; + } else { + thisctr.next_change_time=thisctr.count_binary & 0xFFFF; + } + } else { + thisctr.next_change_time=0; + } + } else { + thisctr.next_change_time=0; + } + } + break; + case 5: + if(data && thisctr.count_written) { //only triggers cause a change. + thisctr.next_change_time=1; + } + break; + default: + break; + } + } + } + } + + bool pit_82C54::read_OUT(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number incorrect in 82C54 read_OUT")); + return 0; + } else { + return counter[cnum].OUTpin; + } + } + + bool pit_82C54::read_GATE(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); + return 0; + } else { + return counter[cnum].GATE; + } + } + +Bit32u pit_82C54::get_clock_event_time(Bit8u cnum) { + if(cnum>MAX_COUNTER) { + BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); + return 0; + } else { + return counter[cnum].next_change_time; + } +} + +Bit32u pit_82C54::get_next_event_time(void) { + Bit32u out; + Bit32u time0=get_clock_event_time(0); + Bit32u time1=get_clock_event_time(1); + Bit32u time2=get_clock_event_time(2); + + out=time0; + if(time1 && (time1<out)) + out=time1; + if(time2 && (time2<out)) + out=time2; + return out; +} |