DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/timer.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <math.h>
00021 #include "dosbox.h"
00022 #include "inout.h"
00023 #include "pic.h"
00024 #include "cpu.h"
00025 #include "mem.h"
00026 #include "mixer.h"
00027 #include "timer.h"
00028 #include "setup.h"
00029 #include "control.h"
00030 
00031 // This is only set in PC-98 mode and only if emulating PC-9801.
00032 // There is at least one game (PC-98 port of Thexder) that depends on PC-9801 PIT 1
00033 // behavior where the counter cycles at all times whether or not the PC speaker is
00034 // "on". This does not force the PC speaker output on (does not force an audible beep),
00035 // it only forces the clock gate on and PIT 1 to cycle.
00036 bool speaker_clock_lock_on = false;
00037 
00038 static INLINE void BIN2BCD(Bit16u& val) {
00039         Bit16u temp=val%10 + (((val/10)%10)<<4)+ (((val/100)%10)<<8) + (((val/1000)%10)<<12);
00040         val=temp;
00041 }
00042 
00043 static INLINE void BCD2BIN(Bit16u& val) {
00044         Bit16u temp= (val&0x0f) +((val>>4)&0x0f) *10 +((val>>8)&0x0f) *100 +((val>>12)&0x0f) *1000;
00045         val=temp;
00046 }
00047 
00048 struct PIT_Block {
00049     struct read_counter_result {
00050         Bit16u          counter = 0xFFFFu;
00051         Bit16u          cycle = 0;          // cycle (Mode 3: 0 or 1)
00052     };
00053 
00054     Bitu cntr = 0;          /* counter value written to 40h-42h as the interval. may take effect immediately (after port 43h) or after count expires */
00055     Bitu cntr_cur = 0;      /* current counter value in effect */
00056     double delay = 0;       /* interval (in ms) between one full count cycle */
00057     double start = 0;       /* time base (in ms) that cycle started at */
00058     double now = 0;         /* current time (in ms) */
00059 
00060     Bit16u read_latch = 0;  /* counter value, latched for read back */
00061     Bit16u write_latch = 0; /* counter value, written by host */
00062 
00063     Bit8u mode = 0;         /* 8254 mode (mode 0 through 5 inclusive) */
00064     Bit8u read_state = 0;   /* 0=read MSB, switch to LSB, 1=LSB only, 2=MSB only, 3=read LSB, switch to MSB, latch next value */
00065     Bit8u write_state = 0;  /* 0=write MSB, switch to LSB, 1=LSB only, 2=MSB only, 3=write MSB, switch to LSB, accept value */
00066     Bit8u cycle_base = 0;
00067 
00068     bool bcd = false;               /* BCD mode */
00069     bool go_read_latch = false;     /* reading should latch another value */
00070     bool new_mode = false;          /* a new mode has been written to port 43h for this timer */
00071     bool counterstatus_set = false; /* set by status_latch(), when using 8254 command to latch multiple counters */
00072     bool counting = false;          /* is counting (?) */
00073     bool update_count = false;      /* update count on completion */
00074 
00075     bool gate = true;       /* gate signal (IN) */
00076     bool output = true;     /* output signal (OUT) */
00077 
00078     read_counter_result     last_counter;       /* what to return when gate == false (not counting) */
00079 
00080     void set_output(bool on) {
00081         output = on;
00082         // TODO: Event callback
00083     }
00084 
00085     void set_next_counter(Bitu new_cntr) {
00086         update_count = true;
00087         cntr = new_cntr;
00088     }
00089     void set_active_counter(Bitu new_cntr) {
00090         assert(new_cntr != 0);
00091 
00092         cntr_cur = new_cntr;
00093         delay = ((double)(1000ul * cntr_cur)) / PIT_TICK_RATE;
00094     }
00095     void latch_next_counter(void) {
00096         set_active_counter(cntr);
00097     }
00098     void reset_count_at(pic_tickindex_t t) {
00099         start = now = t;
00100         cycle_base = 0;
00101     }
00102     void restart_counter_at(pic_tickindex_t t,Bit16u counter) {
00103         double c_delay;
00104 
00105         if (counter == 0)
00106             c_delay = ((double)(1000ull * 0x10000)) / PIT_TICK_RATE;
00107         else
00108             c_delay = ((double)(1000ull * counter)) / PIT_TICK_RATE;
00109 
00110         start = (t - c_delay);
00111     }
00112     void track_time(pic_tickindex_t t) {
00113         now = t;
00114 
00115         /* Mode 0 will always reset the count whether "new mode" or not.
00116          * Mode 1 will count down and stop. TODO: Writing a new counter without "new mode" starts another countdown? */
00117         /* if any periodic mode (Mode 2, 3, 4, 5), then process fully. */
00118         if (mode == 3) {
00119             const double half = delay / 2;
00120 
00121             if (now >= (start+half)) {
00122                 cycle_base = (cycle_base + 1u) & 1u;
00123                 start += half;
00124 
00125                 if (update_count) {
00126                     latch_next_counter();
00127                     update_count = false;
00128                 }
00129 
00130                 if (now >= (start+half)) {
00131                     unsigned int cnt = (unsigned int)floor((now - start) / half);
00132                     cycle_base = (cycle_base + cnt) & 1u;
00133                     start += cnt * half;
00134                 }
00135             }
00136         }
00137         else if (mode >= 2) {
00138             if (now >= (start+delay)) {
00139                 start += delay;
00140 
00141                 if (update_count) {
00142                     latch_next_counter();
00143                     update_count = false;
00144                 }
00145 
00146                 if (now >= (start+delay))
00147                     start += floor((now - start) / delay) * delay;
00148             }
00149         }
00150 
00151         if (now < start)
00152             now = start;
00153     }
00154     double reltime(void) const {
00155         return now - start;
00156     }
00157 
00158     void set_gate(bool on) {
00159         if (gate != on) {
00160             if (!on)/*on=false gate=true*/
00161                 last_counter = read_counter();
00162 
00163             // restart aka "trigger" the counters
00164             switch (mode) {
00165                 case 0:     /* Interrupt on Terminal Count */
00166                 case 4:     /* Software Triggered Strobe */
00167                     restart_counter_at(now,last_counter.counter);
00168                     break;
00169                 case 1:     /* Hardware Triggered one-shot */
00170                     /* output goes LOW when triggered, returns HIGH when counter expires */
00171                     if (on) {
00172                         reset_count_at(now);
00173                         latch_next_counter();
00174                         set_output(false);
00175                     }
00176                     /* TODO */
00177                     break;
00178                 case 2:     /* Rate Generator */
00179                     /* output goes HIGH immediately */
00180                     if (on) {
00181                         reset_count_at(now);
00182                         latch_next_counter();
00183                     }
00184                     else {
00185                         set_output(true);
00186                     }
00187                     /* TODO */
00188                     break;
00189                 case 3:     /* Square Wave Mode */
00190                     if (on) {
00191                         reset_count_at(now);
00192                         latch_next_counter();
00193                     }
00194                     else {
00195                         set_output(true);
00196                     }
00197                     /* TODO */
00198                     break;
00199                 case 5:     /* Hardware Triggered Strobe */
00200                     if (on) {
00201                         reset_count_at(now);
00202                         latch_next_counter();
00203                         set_output(true);
00204                     }
00205                     break;
00206             }
00207 
00208             gate = on;
00209         }
00210     }
00211 
00212     void update_output_from_counter(const read_counter_result &res) {
00213         set_output(get_output_from_counter(res));
00214     }
00215 
00216     bool get_output_from_counter(const read_counter_result &res) {
00217         switch (mode) {
00218             case 0:
00219                 if (new_mode) return false;
00220                 if (res.cycle != 0u/*index > delay*/) return true;
00221                 else return false;
00222                 break;
00223             case 2:
00224                 if (new_mode) return true;
00225                 return res.counter != 0;
00226             case 3:
00227                 if (new_mode) return true;
00228                 return res.cycle == 0;
00229             case 4:
00230                 return true;
00231             default:
00232                 break;
00233         }
00234 
00235         return true;
00236     }
00237 
00238     read_counter_result read_counter(void) const {//This assumes you call track_time()
00239         if (!gate)
00240             return last_counter;
00241 
00242         const double index = reltime();
00243         read_counter_result ret;
00244 
00245         switch (mode) {
00246             case 4:             /* Software Triggered Strobe */
00247             case 0:             /* Interrupt on Terminal Count */
00248                 {
00249                     double tmp;
00250 
00251                     /* Counter keeps on counting after passing terminal count */
00252                     if (bcd) {
00253                         tmp = fmod(index,((double)(1000ul *   10000ul)) / PIT_TICK_RATE);
00254                         ret.counter = (Bit16u)(((unsigned long)(cntr_cur - ((tmp * PIT_TICK_RATE) / 1000.0))) %   10000ul);
00255                     } else {
00256                         tmp = fmod(index,((double)(1000ul * 0x10000ul)) / PIT_TICK_RATE);
00257                         ret.counter = (Bit16u)(((unsigned long)(cntr_cur - ((tmp * PIT_TICK_RATE) / 1000.0))) % 0x10000ul);
00258                     }
00259 
00260                     if (mode == 0) {
00261                         if (index > delay)
00262                             ret.cycle = 1;
00263                     }
00264                 }
00265                 break;
00266             case 5:     /* Hardware Triggered Strobe */
00267             case 1:     /* Hardware Retriggerable one-shot */
00268                 if (index > delay) // has timed out
00269                     ret.counter = 0xFFFF;
00270                 else
00271                     ret.counter = (Bit16u)(cntr_cur - (index * (PIT_TICK_RATE / 1000.0)));
00272                 break;
00273             case 2:             /* Rate Generator */
00274                 ret.counter = (Bit16u)(cntr_cur - ((fmod(index,delay) / delay) * cntr_cur));
00275                 break;
00276             case 3:             /* Square Wave Rate Generator */
00277                 {
00278                     double tmp = fmod(index,(double)delay) * 2;
00279 
00280                     if (tmp < 0) {
00281                         fprintf(stderr,"tmp %.9f index %.9f delay %.9f now %.3f start %.3f\n",tmp,index,delay,now,start);
00282                         abort();
00283                     }
00284 
00285                     ret.cycle = cycle_base;
00286                     if (tmp >= delay) {
00287                         tmp -= delay;
00288                         ret.cycle = (ret.cycle + 1u) & 1u;
00289                     }
00290 
00291                     ret.counter = ((Bit16u)(cntr_cur - ((tmp * cntr_cur) / delay))) & 0xFFFEu; /* always even value */
00292                 }
00293                 break;
00294             default:
00295                 break;
00296         }
00297 
00298         return ret;
00299     }
00300 };
00301 
00302 static PIT_Block pit[3];
00303 
00304 static Bit8u latched_timerstatus;
00305 // the timer status can not be overwritten until it is read or the timer was 
00306 // reprogrammed.
00307 static bool latched_timerstatus_locked;
00308 
00309 unsigned long PIT_TICK_RATE = PIT_TICK_RATE_IBM;
00310 
00311 static void PIT0_Event(Bitu /*val*/) {
00312         PIC_ActivateIRQ(0);
00313         if (pit[0].mode != 0) {
00314                 pit[0].track_time(PIC_FullIndex());
00315 
00316         /* event timing error checking */
00317         double err = PIC_GetCurrentEventTime() - pit[0].start;
00318 
00319         if (err >= (pit[0].delay/2))
00320             err -=  pit[0].delay;
00321 
00322 #if 0//change if debug information wanted
00323         if (fabs(err) >= (0.5 / CPU_CycleMax))
00324             LOG_MSG("PIT0_Event timing error %.6fms",err);
00325 #endif
00326 
00327         PIC_AddEvent(PIT0_Event,pit[0].delay - (err * 0.05));
00328         }
00329 }
00330 
00331 static bool counter_output(Bitu counter) {
00332         PIT_Block *p = &pit[counter];
00333     p->track_time(PIC_FullIndex());
00334 
00335     PIT_Block::read_counter_result res = p->read_counter();
00336     p->update_output_from_counter(res);
00337 
00338     return p->output;
00339 }
00340 static void status_latch(Bitu counter) {
00341         // the timer status can not be overwritten until it is read or the timer was 
00342         // reprogrammed.
00343         if(!latched_timerstatus_locked) {
00344                 PIT_Block * p=&pit[counter];
00345                 latched_timerstatus=0;
00346                 // Timer Status Word
00347                 // 0: BCD 
00348                 // 1-3: Timer mode
00349                 // 4-5: read/load mode
00350                 // 6: "NULL" - this is 0 if "the counter value is in the counter" ;)
00351                 // should rarely be 1 (i.e. on exotic modes)
00352                 // 7: OUT - the logic level on the Timer output pin
00353                 if(p->bcd)latched_timerstatus|=0x1;
00354                 latched_timerstatus|=((p->mode&7)<<1);
00355                 if((p->read_state==0)||(p->read_state==3)) latched_timerstatus|=0x30;
00356                 else if(p->read_state==1) latched_timerstatus|=0x10;
00357                 else if(p->read_state==2) latched_timerstatus|=0x20;
00358                 if(counter_output(counter)) latched_timerstatus|=0x80;
00359                 if(p->new_mode) latched_timerstatus|=0x40;
00360                 // The first thing that is being read from this counter now is the
00361                 // counter status.
00362                 p->counterstatus_set=true;
00363                 latched_timerstatus_locked=true;
00364         }
00365 }
00366 
00367 static void counter_latch(Bitu counter,bool do_latch=true) {
00368         PIT_Block *p = &pit[counter];
00369 
00370     p->track_time(PIC_FullIndex());
00371 
00372     PIT_Block::read_counter_result res = p->read_counter();
00373     p->update_output_from_counter(res);
00374 
00375     if (do_latch) {
00376         p->go_read_latch = false;
00377         p->read_latch = res.counter;
00378     }
00379 
00380     if (counter == 0/*IRQ 0*/) {
00381         if (!p->output)
00382             PIC_DeActivateIRQ(0);
00383     }
00384 }
00385 
00386 void TIMER_IRQ0Poll(void) {
00387     counter_latch(0,false/*do not latch*/);
00388 }
00389 
00390 pic_tickindex_t speaker_pit_delta(void) {
00391     unsigned int speaker_pit = IS_PC98_ARCH ? 1 : 2;
00392     return fmod(pit[speaker_pit].now - pit[speaker_pit].start, pit[speaker_pit].delay);
00393 }
00394 
00395 void speaker_pit_update(void) {
00396     unsigned int speaker_pit = IS_PC98_ARCH ? 1 : 2;
00397     pit[speaker_pit].track_time(PIC_FullIndex());
00398 }
00399 
00400 void PCSPEAKER_UpdateType(void);
00401 
00402 bool TIMER2_ClockGateEnabled(void) {
00403     /* PC speaker emulation should treat "new mode" as if the clock gate is disabled.
00404      * On real hardware, mode 3 does not cycle if you write a control word but then
00405      * do not write a counter value. */
00406     return !pit[IS_PC98_ARCH ? 1 : 2].new_mode;
00407 }
00408 
00409 static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) {
00410 //LOG(LOG_PIT,LOG_ERROR)("port %X write:%X state:%X",port,val,pit[port-0x40].write_state);
00411 
00412     // HACK: Port translation for this code PC-98 mode.
00413     //       0x71,0x73,0x75,0x77 => 0x40-0x43
00414     if (IS_PC98_ARCH) {
00415         if (port >= 0x3FD9)
00416             port = ((port - 0x3FD9) >> 1) + 0x40;
00417         else if (port >=0x71 && port <= 0x75)
00418             port = ((port - 0x71) >> 1) + 0x40;
00419         else {
00420             E_Exit("PIT: PC-98 port in write_latch is out of range.");
00421             return;
00422         }
00423     }
00424 
00425         Bitu counter=port-0x40;
00426         PIT_Block * p=&pit[counter];
00427         if(p->bcd == true) BIN2BCD(p->write_latch);
00428    
00429         switch (p->write_state) {
00430                 case 0:
00431                         p->write_latch = p->write_latch | ((val & 0xff) << 8);
00432                         p->write_state = 3;
00433                         break;
00434                 case 3:
00435                         p->write_latch = val & 0xff;
00436                         p->write_state = 0;
00437                         break;
00438                 case 1:
00439                         p->write_latch = val & 0xff;
00440                         break;
00441                 case 2:
00442                         p->write_latch = (val & 0xff) << 8;
00443                 break;
00444         }
00445         if (p->bcd==true) BCD2BIN(p->write_latch);
00446         if (p->write_state != 0) {
00447         Bitu old_cntr = p->cntr;
00448 
00449         p->track_time(PIC_FullIndex());
00450 
00451         if (p->write_latch == 0) {
00452             if (p->bcd == false)
00453                 p->set_next_counter(0x10000);
00454             else
00455                 p->set_next_counter(9999/*check this*/);
00456         }
00457         else if (p->write_latch == 1 && p->mode == 3/*square wave, count by 2*/) { /* counter==1 and mode==3 makes a low frequency buzz (Paratrooper) */
00458             if (p->bcd == false)
00459                 p->set_next_counter(0x10001);
00460             else
00461                 p->set_next_counter(10000/*check this*/);
00462         }
00463         else {
00464             p->set_next_counter(p->write_latch);
00465         }
00466 
00467         if (!p->new_mode) {
00468             if ((p->mode == 2/*common IBM PC mode*/ || p->mode == 3/*common PC-98 mode*/) && (counter == 0)) {
00469                 // In mode 2 writing another value has no direct effect on the count
00470                 // until the old one has run out. This might apply to other modes too.
00471                 // This is not fixed for PIT2 yet!!
00472                 p->update_count=true;
00473                 return;
00474             }
00475             else if ((p->mode == 3) && (counter == (IS_PC98_ARCH ? 1 : 2))) {
00476                 void PCSPEAKER_SetCounter_NoNewMode(Bitu cntr);
00477 
00478                 // PC speaker
00479                 PCSPEAKER_SetCounter_NoNewMode(p->cntr);
00480                 p->update_count=true;
00481                 return;
00482             }
00483 
00484             if (p->mode == 0) {
00485                 /* Mode 0 is the only mode NOT to wait for the current counter to finish if you write another counter value
00486                  * according to the Intel 8254 datasheet.
00487                  *
00488                  * For timer 0 (system timer) this is used by DoWhackaDo as a sort of one-shot timer interrupt.
00489                  * For timer 2 (PC speaker) this is used to do PWM "realsound" digitized speech in some games. */
00490             }
00491             else {
00492                 // this debug message will help development trace down cases where writing without a new mode
00493                 // would incorrectly restart the counter instead of letting the current count complete before
00494                 // writing a new one.
00495                 LOG(LOG_PIT,LOG_NORMAL)("WARNING: Writing counter %u in mode %u without writing port 43h not yet supported, will be handled as if new mode and reset of the cycle",(int)counter,(int)p->mode);
00496             }
00497         }
00498 
00499         p->reset_count_at(PIC_FullIndex());
00500         p->latch_next_counter();
00501 
00502                 p->new_mode=false;
00503                 switch (counter) {
00504                 case 0x00:                      /* Timer hooked to IRQ 0 */
00505             PIC_RemoveEvents(PIT0_Event);
00506             PIC_AddEvent(PIT0_Event,p->delay);
00507 
00508 #if 0//change to #if 1 if you want to debug Mode 0 one-shot events
00509             if (p->mode == 0)
00510                 LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer one-shot event %.3fms",p->delay);
00511 #endif
00512 
00513             //please do not spam the log and console if a game is writing the SAME counter value constantly,
00514             //and do not spam the console if Mode 0 is used because events are not consistent.
00515             if (p->cntr != old_cntr && p->mode != 0)
00516                 LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.4f Hz mode %d",1000.0/p->delay,p->mode);
00517 
00518             break;
00519         case 0x01:          /* Timer hooked to PC-Speaker (NEC-PC98) */
00520             if (IS_PC98_ARCH)
00521                 PCSPEAKER_SetCounter(p->cntr,p->mode);
00522             break;
00523         case 0x02:                      /* Timer hooked to PC-Speaker (IBM PC) */
00524             if (!IS_PC98_ARCH)
00525                 PCSPEAKER_SetCounter(p->cntr,p->mode);
00526             break;
00527         default:
00528                         LOG(LOG_PIT,LOG_ERROR)("PIT:Illegal timer selected for writing");
00529                 }
00530     }
00531     else { /* write state == 0 */
00532         /* If a new count is written to the Counter, it will be
00533          * loaded on the next CLK pulse and counting will con-
00534          * tinue from the new count. If a two-byte count is writ-
00535          * ten, the following happens:
00536          * 1) Writing the first byte disables counting. OUT is set
00537          * low immediately (no clock pulse required)
00538          * 2) Writing the second byte allows the new count to
00539          * be loaded on the next CLK pulse. */
00540         if (p->mode == 0) {
00541             if (counter == 0) {
00542                 PIC_RemoveEvents(PIT0_Event);
00543                 PIC_DeActivateIRQ(0);
00544             }
00545             p->update_count = false;
00546         }
00547     }
00548 }
00549 
00550 static Bitu read_latch(Bitu port,Bitu /*iolen*/) {
00551 //LOG(LOG_PIT,LOG_ERROR)("port read %X",port);
00552 
00553     // HACK: Port translation for this code PC-98 mode.
00554     //       0x71,0x73,0x75,0x77 => 0x40-0x43
00555     if (IS_PC98_ARCH) {
00556         if (port >= 0x3FD9)
00557             port = ((port - 0x3FD9) >> 1) + 0x40;
00558         else if (port >=0x71 && port <= 0x75)
00559             port = ((port - 0x71) >> 1) + 0x40;
00560         else {
00561             E_Exit("PIT: PC-98 port in read_latch is out of range.");
00562             return 0;
00563         }
00564     }
00565 
00566         Bit32u counter=(Bit32u)(port-0x40);
00567         Bit8u ret=0;
00568         if(GCC_UNLIKELY(pit[counter].counterstatus_set)){
00569                 pit[counter].counterstatus_set = false;
00570                 latched_timerstatus_locked = false;
00571                 ret = latched_timerstatus;
00572         } else {
00573                 if (pit[counter].go_read_latch == true) 
00574                         counter_latch(counter);
00575 
00576                 if( pit[counter].bcd == true) BIN2BCD(pit[counter].read_latch);
00577 
00578                 switch (pit[counter].read_state) {
00579                 case 0: /* read MSB & return to state 3 */
00580                         ret=(pit[counter].read_latch >> 8) & 0xff;
00581                         pit[counter].read_state = 3;
00582                         pit[counter].go_read_latch = true;
00583                         break;
00584                 case 3: /* read LSB followed by MSB */
00585                         ret = pit[counter].read_latch & 0xff;
00586                         pit[counter].read_state = 0;
00587                         break;
00588                 case 1: /* read LSB */
00589                         ret = pit[counter].read_latch & 0xff;
00590                         pit[counter].go_read_latch = true;
00591                         break;
00592                 case 2: /* read MSB */
00593                         ret = (pit[counter].read_latch >> 8) & 0xff;
00594                         pit[counter].go_read_latch = true;
00595                         break;
00596                 default:
00597                         E_Exit("Timer.cpp: error in readlatch");
00598                         break;
00599                 }
00600                 if( pit[counter].bcd == true) BCD2BIN(pit[counter].read_latch);
00601         }
00602         return ret;
00603 }
00604 
00605 static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
00606 //LOG(LOG_PIT,LOG_ERROR)("port 43 %X",val);
00607         Bitu latch=(val >> 6) & 0x03;
00608         switch (latch) {
00609         case 0:
00610         case 1:
00611         case 2:
00612                 if ((val & 0x30) == 0) {
00613                         /* Counter latch command */
00614                         counter_latch(latch);
00615                 } else {
00616                         // save output status to be used with timer 0 irq
00617                         bool old_output = counter_output(0);
00618                         // save the current count value to be re-used in undocumented newmode
00619                         counter_latch(latch);
00620                         pit[latch].bcd = (val&1)>0;   
00621                         if (val & 1) {
00622                                 if(pit[latch].cntr>=9999) pit[latch].cntr=9999;
00623                         }
00624 
00625                         // Timer is being reprogrammed, unlock the status
00626                         if(pit[latch].counterstatus_set) {
00627                                 pit[latch].counterstatus_set=false;
00628                                 latched_timerstatus_locked=false;
00629                         }
00630 //                      pit[latch].reset_count_at(PIC_FullIndex()); // for undocumented newmode
00631                         pit[latch].go_read_latch = true;
00632                         pit[latch].update_count = false;
00633                         pit[latch].counting = false;
00634                         pit[latch].read_state  = (val >> 4) & 0x03;
00635                         pit[latch].write_state = (val >> 4) & 0x03;
00636                         Bit8u mode             = (val >> 1) & 0x07;
00637                         if (mode > 5)
00638                                 mode -= 4; //6,7 become 2 and 3
00639 
00640                         pit[latch].mode = mode;
00641 
00642                         /* If the line goes from low to up => generate irq. 
00643                          *      ( BUT needs to stay up until acknowlegded by the cpu!!! therefore: )
00644                          * If the line goes to low => disable irq.
00645                          * Mode 0 starts with a low line. (so always disable irq)
00646                          * Mode 2,3 start with a high line.
00647                          * counter_output tells if the current counter is high or low 
00648                          * So actually a mode 3 timer enables and disables irq al the time. (not handled) */
00649 
00650             /* Jon C: Oh yeah? Nobody abuses counter == 0 on IBM PC that way, but there is a PC-98
00651              *        game that relies on that behavior: Steel Gun Nyan! */
00652 
00653                         if (latch == 0) {
00654                                 PIC_RemoveEvents(PIT0_Event);
00655                                 if((mode != 0)&& !old_output) {
00656                                         PIC_ActivateIRQ(0);
00657                                 } else {
00658                                         PIC_DeActivateIRQ(0);
00659                                 }
00660                         }
00661                         pit[latch].new_mode = true;
00662                         if (latch == (IS_PC98_ARCH ? 1 : 2)) {
00663                                 // notify pc speaker code that the control word was written.
00664                 // until a counter value is written, the PC speaker should
00665                 // treat the timer as if the clock gate were disabled.
00666                 PCSPEAKER_UpdateType();
00667                 PCSPEAKER_SetPITControl(mode);
00668                         }
00669                 }
00670                 break;
00671     case 3:
00672                 if ((val & 0x20)==0) {  /* Latch multiple pit counters */
00673                         if (val & 0x02) counter_latch(0);
00674                         if (val & 0x04) counter_latch(1);
00675                         if (val & 0x08) counter_latch(2);
00676                 }
00677                 // status and values can be latched simultaneously
00678                 if ((val & 0x10)==0) {  /* Latch status words */
00679                         // but only 1 status can be latched simultaneously
00680                         if (val & 0x02) status_latch(0);
00681                         else if (val & 0x04) status_latch(1);
00682                         else if (val & 0x08) status_latch(2);
00683                 }
00684                 break;
00685         }
00686 }
00687 
00688 // FIXME: I am assuming that the "buzzer inhibit" on PC-98 controls the "trigger" pin
00689 //        that either enables the PIT to count or stops it and resets the counter.
00690 //        Verify this on real hardware (DOSLIB TPCRAPI6.EXE)
00691 //
00692 //        Note that on IBM PC/XT hardware, ports 60h-63h are the same PPI used in the
00693 //        PC-98 systems, though wired differently. It is configured (According to IBM).
00694 //           - Port A (input)           Keyboard scan code / SW1 dip switches (depends on port 61h bit 7)
00695 //           - Port B (output)          Timer 2 gate speaker / Speaker data aka output gate / ... / bit 7 set to clear keyboard and read SW1
00696 //           - Port C (input)           I/O Read/Write Memory SW2 / Cassette Data In / Timer Channel 2 Out / ...
00697 //           - Command byte             0x99 (IBM Technical Ref listing)
00698 //
00699 //        This is the picture I have of the hardware:
00700 //
00701 //        IBM PC/XT:
00702 //
00703 //        Port 61h
00704 //        - bit 0 PIT 2 counter gate (write)
00705 //        - bit 1 PIT 2 counter output gate (write)
00706 //        Port 62h
00707 //        - bit 5 PIT 2 counter output (read). The connection point lies BEFORE the AND gate.
00708 //            You will see the output toggle even if the speaker was muted by clearing the output gate bit.
00709 //
00710 //        IBM PC/AT:
00711 //
00712 //        Port 61h
00713 //        - bit 0 PIT 2 counter gate (write)
00714 //        - bit 1 PIT 2 counter output gate (write)
00715 //        - bit 5 PIT 2 counter output (read). The connection point lies BEFORE the AND gate.
00716 //            You will see the output toggle even if the speaker was muted by clearing the output gate bit.
00717 //
00718 //        PC-98:
00719 //
00720 //        Port 35h (Intel 8255 PPI Port C)
00721 //        - bit 3 PIT 1 counter gate (there is no output gate). Setting the bit inhibits the counter (and therefore PC speaker)
00722 //        - On PC-9821, this bit controls the clock gate of PIT 1 and therefore whether the PC speaker makes sound
00723 //        - On PC-9801, the clock gate of PIT 1 is always on, and this bit controls whether the PC speaker makes sound
00724 //
00725 //        IBM PC/XT/AT:
00726 //
00727 //        counter output readback <- --------+
00728 //                                           |
00729 //                        +------+           |        +----------+
00730 //        counter gate -> | 8254 | -> PIT 2 output -> | AND GATE | -> PC speaker
00731 //                        +------+                    +----------+
00732 //                                                         |
00733 //        counter output gate -> --------------------------+
00734 //
00735 //        PC-9821:
00736 //
00737 //                        +------+
00738 //        counter gate -> | 8254 | -> PC speaker
00739 //                        +------+
00740 //
00741 //        PC-9801:
00742 //
00743 //                        +------+    +----------+
00744 //        logic high ->   | 8254 | -> | AND GATE | -> PC speaker
00745 //         (always on)    +------+    +----------+
00746 //                                         |
00747 //        inverse of bit 3 of port 37h ----+
00748 //          (bit 3 is inhibit)
00749 void TIMER_SetGate2(bool in) {
00750     unsigned int speaker_pit = IS_PC98_ARCH ? 1 : 2;
00751     pit[speaker_pit].track_time(PIC_FullIndex());
00752     pit[speaker_pit].set_gate(in || speaker_clock_lock_on);
00753 }
00754 
00755 bool TIMER_GetOutput2() {
00756     unsigned int speaker_pit = IS_PC98_ARCH ? 1 : 2;//NTS: For completion sake, even though there is no readback bit on PC-98
00757 
00758         return counter_output(speaker_pit);
00759 }
00760 
00761 #include "programs.h"
00762 
00763 static IO_ReadHandleObject ReadHandler[4];
00764 static IO_WriteHandleObject WriteHandler[4];
00765 
00766 /* PC-98 alias */
00767 static IO_ReadHandleObject ReadHandler2[4];
00768 static IO_WriteHandleObject WriteHandler2[4];
00769 
00770 void TIMER_BIOS_INIT_Configure() {
00771         PIC_RemoveEvents(PIT0_Event);
00772         PIC_DeActivateIRQ(0);
00773 
00774         /* Setup Timer 0 */
00775     pit[0].output = true;
00776     pit[0].gate = true;
00777         pit[0].cntr = 0x10000;
00778         pit[0].write_state = 3;
00779         pit[0].read_state = 3;
00780         pit[0].read_latch = 0;
00781         pit[0].write_latch = 0;
00782         pit[0].mode = 3;
00783         pit[0].bcd = false;
00784         pit[0].go_read_latch = true;
00785         pit[0].counterstatus_set = false;
00786         pit[0].update_count = false;
00787         pit[0].reset_count_at(PIC_FullIndex());
00788     pit[0].track_time(PIC_FullIndex());
00789 
00790     pit[1].output = true;
00791     pit[1].gate = true;
00792         pit[1].bcd = false;
00793         pit[1].read_state = 1;
00794         pit[1].go_read_latch = true;
00795         pit[1].cntr = 18;
00796         pit[1].mode = 2;
00797         pit[1].write_state = 3;
00798         pit[1].counterstatus_set = false;
00799         pit[1].reset_count_at(PIC_FullIndex());
00800     pit[1].track_time(PIC_FullIndex());
00801 
00802     pit[2].output = true;
00803     pit[2].gate = false;
00804         pit[2].bcd = false;
00805         pit[2].read_state = 1;
00806         pit[2].go_read_latch = true;
00807         pit[2].cntr = 18;
00808         pit[2].mode = 2;
00809         pit[2].write_state = 3;
00810         pit[2].counterstatus_set = false;
00811         pit[2].reset_count_at(PIC_FullIndex());
00812     pit[2].track_time(PIC_FullIndex());
00813 
00814     /* TODO: I have observed that on real PC-98 hardware:
00815      * 
00816      *   Output 1 (speaker) does not cycle if inhibited by port 35h
00817      *
00818      *   Output 2 (RS232C) does not cycle until programmed to cycle
00819      *   to operate the 8251 for data transfer. It is configured by
00820      *   the BIOS to countdown and stop, thus the UART is not cycling
00821      *   until put into active use. */
00822 
00823     int pcspeaker_pit = IS_PC98_ARCH ? 1 : 2; /* IBM: PC speaker on output 2   PC-98: PC speaker on output 1 */
00824 
00825         {
00826                 Section_prop *pcsec = static_cast<Section_prop *>(control->GetSection("speaker"));
00827                 int freq = pcsec->Get_int("initial frequency"); /* original code: 1320 */
00828                 unsigned int div;
00829 
00830         /* IBM PC defaults to 903Hz.
00831          * NEC PC-98 defaults to 2KHz */
00832         if (freq < 0)
00833             freq = IS_PC98_ARCH ? 2000 : 903;
00834 
00835                 if (freq < 1) {
00836                         div = 65535;
00837                 }
00838                 else {
00839                         div = (unsigned int)PIT_TICK_RATE / (unsigned int)freq;
00840                         if (div > 65535) div = 65535;
00841                 }
00842 
00843                 pit[pcspeaker_pit].cntr = div;
00844                 pit[pcspeaker_pit].read_latch = div;
00845                 pit[pcspeaker_pit].write_state = 3; /* Chuck Yeager */
00846                 pit[pcspeaker_pit].read_state = 3;
00847                 pit[pcspeaker_pit].mode = 3;
00848                 pit[pcspeaker_pit].bcd = false;
00849                 pit[pcspeaker_pit].go_read_latch = true;
00850                 pit[pcspeaker_pit].counterstatus_set = false;
00851                 pit[pcspeaker_pit].counting = false;
00852             pit[pcspeaker_pit].reset_count_at(PIC_FullIndex());
00853         }
00854 
00855         pit[0].latch_next_counter();
00856         pit[1].latch_next_counter();
00857         pit[2].latch_next_counter();
00858 
00859         PCSPEAKER_SetCounter(pit[pcspeaker_pit].cntr,pit[pcspeaker_pit].mode);
00860         PIC_AddEvent(PIT0_Event,pit[0].delay);
00861 
00862     if (IS_PC98_ARCH) {
00863     /* BIOS data area at 0x501 tells the DOS application which clock rate to use */
00864         phys_writeb(0x501,
00865             (phys_readb(0x501) & 0x7F) |
00866             ((PIT_TICK_RATE == PIT_TICK_RATE_PC98_8MHZ) ? 0x80 : 0x00)      /* bit 7: 1=8MHz  0=5MHz/10MHz */
00867             );
00868 
00869         /* Turn off PC speaker.
00870          * Note for PC9801 behavior this will help start the PIT cycling anyway. */
00871         TIMER_SetGate2(false);
00872 
00873         /* The timer is always on, there's no clock gate that I know of.
00874          * There's a bit 6 port 434h that might gate it on some hardware, but that doesn't seem to be the case on anything I have.
00875          *
00876          * NTS: If you run 8254.EXE from DOSLIB on PC-98 hardware and notice PIT 2 isn't cycling, try writing values to 75h
00877          *      and see if it begins counting again. A PC-9821Lt2 laptop seems to have a bios that writes a mode byte for
00878          *      it to 77h but then never writes to 75h, which leaves the timer idle. */
00879         pit[2].track_time(PIC_FullIndex());
00880         pit[2].set_gate(true);
00881     }
00882 }
00883 
00884 void TIMER_OnPowerOn(Section*) {
00885         Section_prop * pc98_section=static_cast<Section_prop *>(control->GetSection("pc98"));
00886         assert(pc98_section != NULL);
00887 
00888         // log
00889         LOG(LOG_MISC,LOG_DEBUG)("TIMER_OnPowerOn(): Reinitializing PIT timer emulation");
00890 
00891         PIC_RemoveEvents(PIT0_Event);
00892 
00893         /* I/O port map (8254)
00894          *
00895          * IBM PC/XT/AT      NEC-PC98     A1-A0
00896          * -----------------------------------
00897          *  0x40              0x71        0
00898          *  0x41              0x73        1
00899          *  0x42              0x75        2
00900          *  0x43              0x77        3
00901          */
00902         /* Timer output connection
00903          * 
00904          * IBM PC/XT/AT      NEC-PC98     Timer
00905          * ------------------------------------
00906          * Timer int.        Timer int.   0
00907          * DRAM refresh      Speaker      1
00908          * Speaker           RS-232C clk  2
00909          *
00910          * If I read documentation correctly, PC-98 wires timer output 2
00911          * to the clock pin of the 8251 UART for COM1 as a way to set the
00912          * baud rate. */
00913 
00914         WriteHandler[0].Uninstall();
00915         WriteHandler[1].Uninstall();
00916         WriteHandler[2].Uninstall();
00917         WriteHandler[3].Uninstall();
00918         ReadHandler[0].Uninstall();
00919         ReadHandler[1].Uninstall();
00920         ReadHandler[2].Uninstall();
00921         ReadHandler[3].Uninstall();
00922 
00923         WriteHandler2[0].Uninstall();
00924         WriteHandler2[1].Uninstall();
00925         WriteHandler2[2].Uninstall();
00926         WriteHandler2[3].Uninstall();
00927         ReadHandler2[0].Uninstall();
00928         ReadHandler2[1].Uninstall();
00929         ReadHandler2[2].Uninstall();
00930         ReadHandler2[3].Uninstall();
00931 
00932     if (IS_PC98_ARCH) {
00933         /* This code is written to eventually copy-paste out in general */
00934         WriteHandler[0].Install(0x71,write_latch,IO_MB);
00935         WriteHandler[1].Install(0x73,write_latch,IO_MB);
00936         WriteHandler[2].Install(0x75,write_latch,IO_MB);
00937         WriteHandler[3].Install(0x77,write_p43,IO_MB);
00938         ReadHandler[0].Install(0x71,read_latch,IO_MB);
00939         ReadHandler[1].Install(0x73,read_latch,IO_MB);
00940         ReadHandler[2].Install(0x75,read_latch,IO_MB);
00941 
00942         /* Apparently all but the first PC-9801 systems have an alias of these
00943          * ports at 0x3FD9-0x3FDF odd. This alias is required for games that
00944          * rely on this alias. */
00945         WriteHandler2[0].Install(0x3FD9,write_latch,IO_MB);
00946         WriteHandler2[1].Install(0x3FDB,write_latch,IO_MB);
00947         WriteHandler2[2].Install(0x3FDD,write_latch,IO_MB);
00948         WriteHandler2[3].Install(0x3FDF,write_p43,IO_MB);
00949         ReadHandler2[0].Install(0x3FD9,read_latch,IO_MB);
00950         ReadHandler2[1].Install(0x3FDB,read_latch,IO_MB);
00951         ReadHandler2[2].Install(0x3FDD,read_latch,IO_MB);
00952     }
00953     else {
00954         WriteHandler[0].Install(0x40,write_latch,IO_MB);
00955 //          WriteHandler[1].Install(0x41,write_latch,IO_MB);
00956         WriteHandler[2].Install(0x42,write_latch,IO_MB);
00957         WriteHandler[3].Install(0x43,write_p43,IO_MB);
00958         ReadHandler[0].Install(0x40,read_latch,IO_MB);
00959         ReadHandler[1].Install(0x41,read_latch,IO_MB);
00960         ReadHandler[2].Install(0x42,read_latch,IO_MB);
00961     }
00962 
00963         latched_timerstatus_locked=false;
00964 
00965     if (IS_PC98_ARCH) {
00966         int pc98rate;
00967 
00968         {
00969             const char *s = pc98_section->Get_string("pc-98 timer always cycles");
00970 
00971             if (!strcmp(s,"true") || !strcmp(s,"1"))
00972                 speaker_clock_lock_on = true; // PC-9801 behavior
00973             else if (!strcmp(s,"false") || !strcmp(s,"0"))
00974                 speaker_clock_lock_on = false; // PC-9821 behavior
00975             else // anything else is handled as "auto"
00976                 speaker_clock_lock_on = false; // PC-9821 behavior
00977         }
00978 
00979         /* PC-98 has two different rates: 5/10MHz base or 8MHz base. Let the user choose via dosbox.conf */
00980         pc98rate = pc98_section->Get_int("pc-98 timer master frequency");
00981         if (pc98rate > 6) pc98rate /= 2;
00982         if (pc98rate == 0) pc98rate = 5; /* Pick the most likely to work with DOS games (FIXME: This is a GUESS!! Is this correct?) */
00983         else if (pc98rate < 5) pc98rate = 4;
00984         else pc98rate = 5;
00985 
00986         if (pc98rate >= 5)
00987             PIT_TICK_RATE = PIT_TICK_RATE_PC98_10MHZ;
00988         else
00989             PIT_TICK_RATE = PIT_TICK_RATE_PC98_8MHZ;
00990 
00991         LOG_MSG("PC-98 PIT master clock rate %luHz",PIT_TICK_RATE);
00992 
00993         latched_timerstatus_locked=false;
00994     }
00995 }
00996 
00997 void TIMER_OnEnterPC98_Phase2_UpdateBDA(void) {
00998         if (!cpu.pmode) {
00999                 /* BIOS data area at 0x501 tells the DOS application which clock rate to use */
01000                 phys_writeb(0x501,
01001             (phys_readb(0x501) & 0x7F) |
01002                         ((PIT_TICK_RATE == PIT_TICK_RATE_PC98_8MHZ) ? 0x80 : 0x00)      /* bit 7: 1=8MHz  0=5MHz/10MHz */
01003                 );
01004         }
01005         else {
01006                 LOG_MSG("PC-98 warning: PIT timer change cannot be reflected to BIOS data area in protected/vm86 mode");
01007         }
01008 }
01009 
01010 void TIMER_Destroy(Section*) {
01011         PIC_RemoveEvents(PIT0_Event);
01012 }
01013 
01014 void TIMER_Init() {
01015         Bitu i;
01016 
01017         LOG(LOG_MISC,LOG_DEBUG)("TIMER_Init()");
01018 
01019     PIT_TICK_RATE = PIT_TICK_RATE_IBM;
01020 
01021         for (i=0;i < 3;i++) {
01022                 pit[i].cntr = 0x10000;
01023                 pit[i].write_state = 0;
01024                 pit[i].read_state = 0;
01025                 pit[i].read_latch = 0;
01026                 pit[i].write_latch = 0;
01027                 pit[i].mode = 0;
01028                 pit[i].bcd = false;
01029                 pit[i].go_read_latch = false;
01030                 pit[i].counterstatus_set = false;
01031                 pit[i].update_count = false;
01032         pit[i].latch_next_counter();
01033         }
01034 
01035         AddExitFunction(AddExitFunctionFuncPair(TIMER_Destroy));
01036         AddVMEventFunction(VM_EVENT_POWERON, AddVMEventFunctionFuncPair(TIMER_OnPowerOn));
01037 }
01038 
01039 //save state support
01040 void *PIT0_Event_PIC_Event = (void*)((uintptr_t)PIT0_Event);
01041 
01042 namespace
01043 {
01044 class SerializeTimer : public SerializeGlobalPOD
01045 {
01046 public:
01047     SerializeTimer() : SerializeGlobalPOD("IntTimer10")
01048     {
01049         registerPOD(pit);
01050         //registerPOD(gate2);
01051         registerPOD(latched_timerstatus);
01052                 registerPOD(latched_timerstatus_locked);
01053     }
01054 } dummy;
01055 }