//////////////////////////////////////////////////////////////////////// // $Id: pit_wrap.cc,v 1.50 2003-06-07 19:16:54 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //Realtime Algorithm (with gettimeofday) // HAVE: // Real number of usec. // Emulated number of usec. // WANT: // Number of ticks to use. // Number of emulated usec to wait until next try. // // ticks=number of ticks needed to match total real usec. // if(desired ticks > max ticks for elapsed real time) // ticks = max ticks for elapsed real time. // if(desired ticks > max ticks for elapsed emulated usec) // ticks = max ticks for emulated usec. // next wait ticks = number of ticks until next event. // next wait real usec = (current ticks + next wait ticks) * usec per ticks // next wait emulated usec = next wait real usec * emulated usec / real usec // if(next wait emulated usec < minimum emulated usec for next wait ticks) // next wait emulated usec = minimum emulated usec for next wait ticks. // if(next wait emulated usec > max emulated usec wait) // next wait emulated usec = max emulated usec wait. // // How to calculate elapsed real time: // store an unused time value whenever no ticks are used in a given time. // add this to the current elapsed time. // How to calculate elapsed emulated time: // same as above. // Above can be done by not updating last_usec and last_sec. // // How to calculate emulated usec/real usec: // Each time there are actual ticks: // Alpha_product(old emulated usec, emulated usec); // Alpha_product(old real usec, real usec); // Divide resulting values. #include "bochs.h" #if BX_USE_NEW_PIT #include "pit_wrap.h" //Important constant #defines: #define USEC_PER_SECOND (1000000) //1.193181MHz Clock #define TICKS_PER_SECOND (1193181) // define a macro to convert floating point numbers into 64-bit integers. // In MSVC++ you can convert a 64-bit float into a 64-bit signed integer, // but it will not convert a 64-bit float into a 64-bit unsigned integer. // This macro works around that. #define F2I(x) ((Bit64u)(Bit64s) (x)) #define I2F(x) ((double)(Bit64s) (x)) //CONFIGURATION #defines: //MAINLINE Configuration (For realtime PIT): //How much faster than real time we can go: #define MAX_MULT (1.25) //Minimum number of emulated useconds per second. // Now calculated using BX_MIN_IPS, the minimum number of // instructions per second. #if 1 # define MIN_USEC_PER_SECOND (((((Bit64u)USEC_PER_SECOND)*((Bit64u)BX_MIN_IPS))/((Bit64u)(bx_options.Oips->get())))+(Bit64u)1) #else # define MIN_USEC_PER_SECOND (150000) #endif #if !BX_HAVE_REALTIME_USEC //These are only used if we don't have a way of getting accurate time. //How much slower than real time we can go: # define MIN_MULT (0.9) //How much farther ahead we can get before we just stop // and wait for real time to catch up: # define AHEAD_CEILING ((Bit64u)(TICKS_PER_SECOND*2)) #endif //DEBUG configuration: //Debug with printf options. #define DEBUG_REALTIME_WITH_PRINTF 0 //Use to test execution at multiples of real time. #define TIME_DIVIDER (1) #define TIME_MULTIPLIER (1) #define TIME_HEADSTART (0) #define GET_PIT_REALTIME64_USEC() (((bx_get_realtime64_usec()*(Bit64u)TIME_MULTIPLIER/(Bit64u)TIME_DIVIDER))) //Set up Logging. #define LOG_THIS bx_pit. //A single instance. bx_pit_c bx_pit; #if BX_USE_PIT_SMF #define this (&bx_pit) #endif //Workaround for environments where OUT is defined. #ifdef OUT # undef OUT #endif //Generic MAX and MIN Functions #define BX_MAX(a,b) ( ((a)>(b))?(a):(b) ) #define BX_MIN(a,b) ( ((a)>(b))?(b):(a) ) //USEC_ALPHA is multiplier for the past. //USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present. #define USEC_ALPHA ((double)(.8)) #define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA)) #define USEC_ALPHA2 ((double)(.5)) #define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2)) #define ALPHA_LOWER(old,new) ((Bit64u)((oldget (); BX_PIT_THIS s.timer.init(); Bit64u my_time_usec = bx_virt_timer.time_usec(); if (BX_PIT_THIS s.timer_handle[0] == BX_NULL_TIMER_HANDLE) { BX_PIT_THIS s.timer_handle[0] = bx_virt_timer.register_timer(this, timer_handler, (unsigned) 100 , 1, 1, "pit_wrap"); } BX_DEBUG(("pit: RESETting timer.")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer.")); if(BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer.")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); BX_PIT_THIS s.last_usec=my_time_usec; BX_PIT_THIS s.total_ticks=0; if (BX_PIT_THIS s.use_realtime) { BX_PIT_THIS s.usec_per_second=USEC_PER_SECOND; BX_PIT_THIS s.ticks_per_second=TICKS_PER_SECOND; BX_PIT_THIS s.total_sec=0; BX_PIT_THIS s.stored_delta=0; #if BX_HAVE_REALTIME_USEC BX_PIT_THIS s.last_time=GET_PIT_REALTIME64_USEC()+(Bit64u)TIME_HEADSTART*(Bit64u)USEC_PER_SECOND; BX_PIT_THIS s.em_last_realtime=0; BX_PIT_THIS s.last_realtime_delta=0; BX_PIT_THIS s.last_realtime_ticks=0; #else BX_PIT_THIS s.last_time=((time(NULL)*TIME_MULTIPLIER/TIME_DIVIDER)+TIME_HEADSTART)*USEC_PER_SECOND; BX_PIT_THIS s.max_ticks = AHEAD_CEILING; #endif } else { BX_PIT_THIS s.total_usec=0; } BX_DEBUG(("pit: finished init")); BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%d",BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time)); return(1); } void bx_pit_c::reset(unsigned type) { } void bx_pit_c::timer_handler(void *this_ptr) { bx_pit_c * class_ptr = (bx_pit_c *) this_ptr; class_ptr->handle_timer(); } void bx_pit_c::handle_timer() { Bit64u my_time_usec = bx_virt_timer.time_usec(); Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; Bit32u time_passed32 = (Bit32u)time_passed; BX_DEBUG(("pit: entering timer handler")); if(time_passed32) { periodic(time_passed32); } BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed; if(time_passed || (BX_PIT_THIS s.last_next_event_time != BX_PIT_THIS s.timer.get_next_event_time()) ) { BX_DEBUG(("pit: RESETting timer.")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer.")); if(BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer.")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); } BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time)); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PIT_SMF bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; return( class_ptr->read(address, io_len) ); } Bit32u bx_pit_c::read( Bit32u address, unsigned int io_len ) { #else UNUSED(this_ptr); #endif // !BX_USE_PIT_SMF BX_DEBUG(("pit: entering read handler")); handle_timer(); Bit64u my_time_usec = bx_virt_timer.time_usec(); if (io_len > 1) BX_PANIC(("pit: io read from port %04x, len=%u", (unsigned) address, (unsigned) io_len)); if (bx_dbg.pit) BX_INFO(("pit: io read from port %04x", (unsigned) address)); switch (address) { case 0x40: /* timer 0 - system ticks */ return(BX_PIT_THIS s.timer.read(0)); break; case 0x41: /* timer 1 read */ return(BX_PIT_THIS s.timer.read(1)); break; case 0x42: /* timer 2 read */ return(BX_PIT_THIS s.timer.read(2)); break; case 0x43: /* timer 1 read */ return(BX_PIT_THIS s.timer.read(3)); break; case 0x61: /* AT, port 61h */ BX_PIT_THIS s.refresh_clock_div2 = (bx_bool)((my_time_usec / 15) & 1); return( (BX_PIT_THIS s.timer.read_OUT(2)<<5) | (BX_PIT_THIS s.refresh_clock_div2<<4) | (BX_PIT_THIS s.speaker_data_on<<1) | (BX_PIT_THIS s.timer.read_GATE(2)?1:0) ); break; default: BX_PANIC(("pit: unsupported io read from port %04x", address)); } return(0); /* keep compiler happy */ } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len) { #if !BX_USE_PIT_SMF bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; class_ptr->write(address, dvalue, io_len); } void bx_pit_c::write( Bit32u address, Bit32u dvalue, unsigned int io_len ) { #else UNUSED(this_ptr); #endif // !BX_USE_PIT_SMF Bit8u value; Bit64u my_time_usec = bx_virt_timer.time_usec(); Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; Bit32u time_passed32 = (Bit32u)time_passed; BX_DEBUG(("pit: entering write handler")); if(time_passed32) { periodic(time_passed32); } BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed; value = (Bit8u ) dvalue; if (io_len > 1) BX_PANIC(("pit: io write to port %04x, len=%u", (unsigned) address, (unsigned) io_len)); if (bx_dbg.pit) BX_INFO(("pit: write to port %04x = %02x", (unsigned) address, (unsigned) value)); switch (address) { case 0x40: /* timer 0: write count register */ BX_PIT_THIS s.timer.write(0,value); break; case 0x41: /* timer 1: write count register */ BX_PIT_THIS s.timer.write( 1,value ); break; case 0x42: /* timer 2: write count register */ BX_PIT_THIS s.timer.write( 2,value ); break; case 0x43: /* timer 0-2 mode control */ BX_PIT_THIS s.timer.write( 3,value ); break; case 0x61: BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01; /*??? only on AT+ */ BX_PIT_THIS s.timer.set_GATE(2, value & 0x01); #if BX_CPU_LEVEL < 2 /* ??? XT: */ bx_kbd_port61h_write(value); #endif break; default: BX_PANIC(("pit: unsupported io write to port %04x = %02x", (unsigned) address, (unsigned) value)); } if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { DEV_pic_raise_irq(0); } else { DEV_pic_lower_irq(0); } if(time_passed || (BX_PIT_THIS s.last_next_event_time != BX_PIT_THIS s.timer.get_next_event_time()) ) { BX_DEBUG(("pit: RESETting timer.")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer.")); if(BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer.")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); } BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time)); } int bx_pit_c::SaveState( class state_file *fd ) { fd->write_check ("8254 start"); fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); fd->write_check ("8254 end"); return(0); } int bx_pit_c::LoadState( class state_file *fd ) { fd->read_check ("8254 start"); fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); fd->read_check ("8254 end"); return(0); } #if 0 void bx_kbd_port61h_write(Bit8u value) { // PcError("KBD_PORT61H_WRITE(): not implemented yet"); UNUSED( value ); } #endif bx_bool bx_pit_c::periodic( Bit32u usec_delta ) { bx_bool prev_timer0_out = BX_PIT_THIS s.timer.read_OUT(0); bx_bool want_interrupt = 0; Bit32u ticks_delta = 0; #ifdef BX_SCHEDULED_DIE_TIME if (bx_pc_system.time_ticks() > BX_SCHEDULED_DIE_TIME) { BX_ERROR (("ticks exceeded scheduled die time, quitting")); BX_EXIT (2); } #endif if (BX_PIT_THIS s.use_realtime) { #if BX_HAVE_REALTIME_USEC Bit64u real_time_delta = GET_PIT_REALTIME64_USEC() - BX_PIT_THIS s.last_time; Bit64u real_time_total = real_time_delta + BX_PIT_THIS s.total_sec; Bit64u em_time_delta = (Bit64u)usec_delta + (Bit64u)BX_PIT_THIS s.stored_delta; if(real_time_delta) { BX_PIT_THIS s.last_realtime_delta = real_time_delta; BX_PIT_THIS s.last_realtime_ticks = BX_PIT_THIS s.total_ticks; } BX_PIT_THIS s.ticks_per_second = TICKS_PER_SECOND; //Start out with the number of ticks we would like // to have to line up with real time. ticks_delta = (Bit32u)(REAL_USEC_TO_TICKS(real_time_total) - BX_PIT_THIS s.total_ticks); if(REAL_USEC_TO_TICKS(real_time_total) < BX_PIT_THIS s.total_ticks) { //This slows us down if we're already ahead. // probably only an issue on startup, but it solves some problems. ticks_delta = 0; } if(ticks_delta + BX_PIT_THIS s.total_ticks - BX_PIT_THIS s.last_realtime_ticks > REAL_USEC_TO_TICKS(F2I(MAX_MULT * I2F(BX_PIT_THIS s.last_realtime_delta)))) { //This keeps us from going too fast in relation to real time. ticks_delta = (Bit32u)(REAL_USEC_TO_TICKS(F2I(MAX_MULT * I2F(BX_PIT_THIS s.last_realtime_delta))) + BX_PIT_THIS s.last_realtime_ticks - BX_PIT_THIS s.total_ticks); BX_PIT_THIS s.ticks_per_second = F2I(MAX_MULT * I2F(TICKS_PER_SECOND)); } if(ticks_delta > em_time_delta * TICKS_PER_SECOND / MIN_USEC_PER_SECOND) { //This keeps us from having too few instructions between ticks. ticks_delta = (Bit32u)(em_time_delta * TICKS_PER_SECOND / MIN_USEC_PER_SECOND); } if(ticks_delta > BX_PIT_THIS s.timer.get_next_event_time()) { //This keeps us from missing ticks. ticks_delta = BX_PIT_THIS s.timer.get_next_event_time(); } if(ticks_delta) { # if DEBUG_REALTIME_WITH_PRINTF if(((BX_PIT_THIS s.last_time + real_time_delta) / USEC_PER_SECOND) > (BX_PIT_THIS s.last_time / USEC_PER_SECOND)) { Bit64u temp1, temp2, temp3, temp4; temp1 = (Bit64u) BX_PIT_THIS s.total_sec; temp2 = REAL_USEC_TO_TICKS(BX_PIT_THIS s.total_sec); temp3 = (Bit64u)BX_PIT_THIS s.total_ticks; temp4 = (Bit64u)(REAL_USEC_TO_TICKS(BX_PIT_THIS s.total_sec) - BX_PIT_THIS s.total_ticks); printf("useconds: " FMT_LL "u, ",temp1); printf("expect ticks: " FMT_LL "u, ",temp2); printf("ticks: " FMT_LL "u, ",temp3); printf("diff: " FMT_LL "u\n",temp4); } # endif BX_PIT_THIS s.last_time += real_time_delta; BX_PIT_THIS s.total_sec += real_time_delta; BX_PIT_THIS s.last_sec_usec += em_time_delta; // BX_PIT_THIS s.total_usec += em_time_delta; BX_PIT_THIS s.stored_delta = 0; BX_PIT_THIS s.total_ticks += ticks_delta; } else { BX_PIT_THIS s.stored_delta = em_time_delta; } Bit64u a,b; a=(BX_PIT_THIS s.usec_per_second); if(real_time_delta) { //FIXME Bit64u em_realtime_delta = BX_PIT_THIS s.last_sec_usec + BX_PIT_THIS s.stored_delta - BX_PIT_THIS s.em_last_realtime; b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta); BX_PIT_THIS s.em_last_realtime = BX_PIT_THIS s.last_sec_usec + BX_PIT_THIS s.stored_delta; } else { b=a; } BX_PIT_THIS s.usec_per_second = ALPHA_LOWER(a,b); #else ticks_delta=(Bit32u)(USEC_TO_TICKS(usec_delta)); if((BX_PIT_THIS s.total_ticks + ticks_delta) < (BX_PIT_THIS s.max_ticks)) { BX_PIT_THIS s.total_ticks += ticks_delta; } else { if(BX_PIT_THIS s.total_ticks >= (BX_PIT_THIS s.max_ticks)) { ticks_delta = 0; } else { ticks_delta = (BX_PIT_THIS s.max_ticks) - BX_PIT_THIS s.total_ticks; BX_PIT_THIS s.total_ticks += ticks_delta; } } second_update_data(); #endif } else { BX_PIT_THIS s.total_usec += usec_delta; ticks_delta=(Bit32u)((USEC_TO_TICKS((Bit64u)(BX_PIT_THIS s.total_usec)))-BX_PIT_THIS s.total_ticks); BX_PIT_THIS s.total_ticks += ticks_delta; while ((BX_PIT_THIS s.total_ticks >= TICKS_PER_SECOND) && (BX_PIT_THIS s.total_usec >= USEC_PER_SECOND)) { BX_PIT_THIS s.total_ticks -= TICKS_PER_SECOND; BX_PIT_THIS s.total_usec -= USEC_PER_SECOND; } } while(ticks_delta>0) { Bit32u maxchange=BX_PIT_THIS s.timer.get_next_event_time(); Bit32u timedelta=maxchange; if((maxchange==0) || (maxchange>ticks_delta)) { timedelta=ticks_delta; } BX_PIT_THIS s.timer.clock_all(timedelta); if ( (prev_timer0_out==0) ) { if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { DEV_pic_raise_irq(0); prev_timer0_out=1; } } else { if ((BX_PIT_THIS s.timer.read_OUT(0))==0) { DEV_pic_lower_irq(0); prev_timer0_out=0; } } prev_timer0_out=BX_PIT_THIS s.timer.read_OUT(0); ticks_delta-=timedelta; } return(want_interrupt); } #if !BX_HAVE_REALTIME_USEC void bx_pit_c::second_update_data(void) { Bit64u my_time_usec = bx_virt_timer.time_usec(); Bit64u timediff; timediff=((time(NULL)*TIME_MULTIPLIER/TIME_DIVIDER)*USEC_PER_SECOND)-BX_PIT_THIS s.last_time; BX_PIT_THIS s.last_time += timediff; if(timediff) { Bit64s tickstemp; BX_PIT_THIS s.total_sec += timediff; BX_PIT_THIS s.max_ticks = BX_MIN( (((BX_PIT_THIS s.total_sec)*(Bit64u)(TICKS_PER_SECOND))/USEC_PER_SECOND) + AHEAD_CEILING , BX_PIT_THIS s.total_ticks + (Bit64u)(TICKS_PER_SECOND*MAX_MULT) ); #if DEBUG_REALTIME_WITH_PRINTF printf("timediff: " FMT_LL "u, total_sec: " FMT_LL "u, total_ticks: " FMT_LL "u\n",timediff, BX_PIT_THIS s.total_sec, BX_PIT_THIS s.total_ticks); #endif tickstemp = ((((BX_PIT_THIS s.total_sec)*TICKS_PER_SECOND)/USEC_PER_SECOND)-BX_PIT_THIS s.total_ticks) + TICKS_PER_SECOND; // while((BX_PIT_THIS s.total_sec >= 0) && (BX_PIT_THIS s.total_ticks >= TICKS_PER_SECOND)) { // BX_PIT_THIS s.total_sec -= 1; // BX_PIT_THIS s.total_ticks -= TICKS_PER_SECOND; // } if(tickstemp > (TICKS_PER_SECOND*MAX_MULT)) { #if DEBUG_REALTIME_WITH_PRINTF if (tickstemp>(2*TICKS_PER_SECOND)) { printf("Running WAY too slow. tps:" FMT_LL "u\n",tickstemp); } else { printf("Running slow. tps:" FMT_LL "u\n",tickstemp); } #endif tickstemp = (Bit64u)(TICKS_PER_SECOND*MAX_MULT); #if DEBUG_REALTIME_WITH_PRINTF printf("..................new tps:" FMT_LL "u\n",tickstemp); #endif } else if(tickstemp < (TICKS_PER_SECOND*MIN_MULT)) { #if DEBUG_REALTIME_WITH_PRINTF if(tickstemp<0) { printf("Running WAY too fast. tps:" FMT_LL "u\n",tickstemp); } else { printf("Running fast. tps:" FMT_LL "u\n",tickstemp); } #endif tickstemp = (Bit64u)(TICKS_PER_SECOND*MIN_MULT); #if DEBUG_REALTIME_WITH_PRINTF printf("..................new tps:" FMT_LL "u\n",tickstemp); #endif } BX_PIT_THIS s.ticks_per_second = tickstemp; // BX_PIT_THIS s.usec_per_second = ALPHA_LOWER(BX_PIT_THIS s.usec_per_second,((my_time_usec-BX_PIT_THIS s.last_sec_usec)*USEC_PER_SECOND/timediff)); BX_PIT_THIS s.usec_per_second = ((my_time_usec-BX_PIT_THIS s.last_sec_usec)*USEC_PER_SECOND/timediff); BX_PIT_THIS s.usec_per_second = BX_MAX(BX_PIT_THIS s.usec_per_second , MIN_USEC_PER_SECOND); BX_PIT_THIS s.last_sec_usec = my_time_usec; #if DEBUG_REALTIME_WITH_PRINTF printf("Parms: ticks_per_second=" FMT_LL "u, usec_per_second=" FMT_LL "u\n",BX_PIT_THIS s.ticks_per_second, BX_PIT_THIS s.usec_per_second); printf("total_usec: " FMT_LL "u\n", my_time_usec); #endif } } #endif // #if !BX_HAVE_REALTIME_USEC #endif // #if BX_USE_NEW_PIT