1 /////////////////////////////////////////////////////////////////////////
2 // $Id: pit82c54.cc 14109 2021-01-30 23:55:24Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 
21 /*
22  * Emulator of an Intel 8254/82C54 Programmable Interval Timer.
23  * Greg Alexander <yakovlev@usa.com>
24  *
25  *
26  * Things I am unclear on (greg):
27  * 1.)What happens if both the status and count registers are latched,
28  *  but the first of the two count registers has already been read?
29  *  I.E.:
30  *   latch count 0 (16-bit)
31  *   Read count 0 (read LSByte)
32  *   READ_BACK status of count 0
33  *   Read count 0 - do you get MSByte or status?
34  *  This will be flagged as an error.
35  * 2.)What happens when we latch the output in the middle of a 2-part
36  *  unlatched read?
37  * 3.)I assumed that programming a counter removes a latched status.
38  * 4.)I implemented the 8254 description of mode 0, not the 82C54 one.
39  * 5.)clock() calls represent a rising clock edge followed by a falling
40  *  clock edge.
41  * 6.)What happens when we trigger mode 1 in the middle of a 2-part
42  *  write?
43  */
44 
45 // Define BX_PLUGGABLE in files that can be compiled into plugins.  For
46 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
47 // is used to know when we are exporting symbols and when we are importing.
48 #define BX_PLUGGABLE
49 
50 #include "iodev.h"
51 #include "pit82c54.h"
52 #define LOG_THIS this->
53 
54 
print_counter(counter_type & thisctr)55 void pit_82C54::print_counter(counter_type &thisctr)
56 {
57 #if BX_DEBUGGER
58   dbg_printf("count: %d\n", thisctr.count);
59   dbg_printf("count_binary: 0x%04x\n", thisctr.count_binary);
60   dbg_printf("counter GATE: %x\n", thisctr.GATE);
61   dbg_printf("counter OUT: %x\n", thisctr.OUTpin);
62   dbg_printf("next_change_time: %d\n", thisctr.next_change_time);
63 #endif
64 }
65 
print_cnum(Bit8u cnum)66 void pit_82C54::print_cnum(Bit8u cnum)
67 {
68   if (cnum>MAX_COUNTER) {
69     BX_ERROR(("Bad counter index to print_cnum"));
70   } else {
71     print_counter(counter[cnum]);
72   }
73 }
74 
latch_counter(counter_type & thisctr)75 void pit_82C54::latch_counter(counter_type &thisctr)
76 {
77     if (thisctr.count_LSB_latched || thisctr.count_MSB_latched) {
78       //Do nothing because previous latch has not been read.;
79     } else {
80       switch(thisctr.read_state) {
81       case MSByte:
82         thisctr.outlatch=thisctr.count & 0xFFFF;
83         thisctr.count_MSB_latched=1;
84         break;
85       case LSByte:
86         thisctr.outlatch=thisctr.count & 0xFFFF;
87         thisctr.count_LSB_latched=1;
88         break;
89       case LSByte_multiple:
90         thisctr.outlatch=thisctr.count & 0xFFFF;
91         thisctr.count_LSB_latched=1;
92         thisctr.count_MSB_latched=1;
93         break;
94       case MSByte_multiple:
95         if (!(seen_problems & UNL_2P_READ)) {
96 //          seen_problems|=UNL_2P_READ;
97           BX_ERROR(("Unknown behavior when latching during 2-part read."));
98           BX_ERROR(("  This message will not be repeated."));
99         }
100         //I guess latching and resetting to LSB first makes sense;
101         BX_DEBUG(("Setting read_state to LSB_mult"));
102         thisctr.read_state=LSByte_multiple;
103         thisctr.outlatch=thisctr.count & 0xFFFF;
104         thisctr.count_LSB_latched=1;
105         thisctr.count_MSB_latched=1;
106         break;
107       default:
108         BX_ERROR(("Unknown read mode found during latch command."));
109         break;
110       }
111     }
112 }
113 
set_OUT(counter_type & thisctr,bool data)114 void pit_82C54::set_OUT(counter_type &thisctr, bool data)
115 {
116   if (thisctr.OUTpin != data) {
117     thisctr.OUTpin = data;
118     if (thisctr.out_handler != NULL) {
119       thisctr.out_handler(data);
120     }
121   }
122 }
123 
set_count(counter_type & thisctr,Bit32u data)124 void BX_CPP_AttrRegparmN(2) pit_82C54::set_count(counter_type &thisctr, Bit32u data)
125 {
126   thisctr.count=data & 0xFFFF;
127   set_binary_to_count(thisctr);
128 }
129 
set_count_to_binary(counter_type & thisctr)130 void BX_CPP_AttrRegparmN(1) pit_82C54::set_count_to_binary(counter_type &thisctr)
131 {
132   if (thisctr.bcd_mode) {
133     thisctr.count=
134       (((thisctr.count_binary/1)%10)<<0) |
135       (((thisctr.count_binary/10)%10)<<4) |
136       (((thisctr.count_binary/100)%10)<<8) |
137       (((thisctr.count_binary/1000)%10)<<12);
138   } else {
139     thisctr.count=thisctr.count_binary;
140   }
141 }
142 
set_binary_to_count(counter_type & thisctr)143 void BX_CPP_AttrRegparmN(1) pit_82C54::set_binary_to_count(counter_type &thisctr)
144 {
145   if (thisctr.bcd_mode) {
146     thisctr.count_binary=
147       (1*((thisctr.count>>0)&0xF)) +
148       (10*((thisctr.count>>4)&0xF)) +
149       (100*((thisctr.count>>8)&0xF)) +
150       (1000*((thisctr.count>>12)&0xF));
151   } else {
152     thisctr.count_binary=thisctr.count;
153   }
154 }
155 
decrement(counter_type & thisctr)156 void BX_CPP_AttrRegparmN(1) pit_82C54::decrement (counter_type &thisctr)
157 {
158   if (!thisctr.count) {
159     if (thisctr.bcd_mode) {
160       thisctr.count=0x9999;
161       thisctr.count_binary=9999;
162     } else {
163       thisctr.count=0xFFFF;
164       thisctr.count_binary=0xFFFF;
165     }
166   } else {
167     thisctr.count_binary--;
168     set_count_to_binary(thisctr);
169   }
170 }
171 
init(void)172 void pit_82C54::init(void)
173 {
174   put("pit82c54", "PIT81");
175 
176   for(int i=0;i<3;i++) {
177     BX_DEBUG(("Setting read_state to LSB"));
178     counter[i].read_state=LSByte;
179     counter[i].write_state=LSByte;
180     counter[i].GATE=1;
181     counter[i].OUTpin=1;
182     counter[i].triggerGATE=0;
183     counter[i].mode=4;
184     counter[i].first_pass=0;
185     counter[i].bcd_mode=0;
186     counter[i].count=0;
187     counter[i].count_binary=0;
188     counter[i].state_bit_1=0;
189     counter[i].state_bit_2=0;
190     counter[i].null_count=0;
191     counter[i].rw_mode=1;
192     counter[i].count_written=1;
193     counter[i].count_LSB_latched=0;
194     counter[i].count_MSB_latched=0;
195     counter[i].status_latched=0;
196     counter[i].next_change_time=0;
197     counter[i].out_handler=NULL;
198   }
199   seen_problems=0;
200 }
201 
pit_82C54(void)202 pit_82C54::pit_82C54(void)
203 {
204   init();
205 }
206 
reset(unsigned type)207 void pit_82C54::reset(unsigned type) {}
208 
register_state(bx_param_c * parent)209 void pit_82C54::register_state(bx_param_c *parent)
210 {
211   char name[4];
212 
213   for (unsigned i=0; i<3; i++) {
214     sprintf(name, "%u", i);
215     bx_list_c *tim = new bx_list_c(parent, name);
216     BXRS_PARAM_BOOL(tim, GATE, counter[i].GATE);
217     BXRS_PARAM_BOOL(tim, OUTpin, counter[i].OUTpin);
218     new bx_shadow_num_c(tim, "count", &counter[i].count);
219     new bx_shadow_num_c(tim, "outlatch", &counter[i].outlatch);
220     new bx_shadow_num_c(tim, "inlatch", &counter[i].inlatch);
221     new bx_shadow_num_c(tim, "status_latch", &counter[i].status_latch);
222     new bx_shadow_num_c(tim, "rw_mode", &counter[i].rw_mode);
223     new bx_shadow_num_c(tim, "mode", &counter[i].mode);
224     BXRS_PARAM_BOOL(tim, bcd_mode, counter[i].bcd_mode);
225     BXRS_PARAM_BOOL(tim, null_count, counter[i].null_count);
226     BXRS_PARAM_BOOL(tim, count_LSB_latched, counter[i].count_LSB_latched);
227     BXRS_PARAM_BOOL(tim, count_MSB_latched, counter[i].count_MSB_latched);
228     BXRS_PARAM_BOOL(tim, status_latched, counter[i].status_latched);
229     new bx_shadow_num_c(tim, "count_binary", &counter[i].count_binary);
230     BXRS_PARAM_BOOL(tim, triggerGATE, counter[i].triggerGATE);
231     new bx_shadow_num_c(tim, "write_state", (Bit8u*)&counter[i].write_state);
232     new bx_shadow_num_c(tim, "read_state", (Bit8u*)&counter[i].read_state);
233     BXRS_PARAM_BOOL(tim, count_written, counter[i].count_written);
234     BXRS_PARAM_BOOL(tim, first_pass, counter[i].first_pass);
235     BXRS_PARAM_BOOL(tim, state_bit_1, counter[i].state_bit_1);
236     BXRS_PARAM_BOOL(tim, state_bit_2, counter[i].state_bit_2);
237     new bx_shadow_num_c(tim, "next_change_time", &counter[i].next_change_time);
238   }
239 }
240 
decrement_multiple(counter_type & thisctr,Bit32u cycles)241 void BX_CPP_AttrRegparmN(2) pit_82C54::decrement_multiple(counter_type &thisctr, Bit32u cycles)
242 {
243   while(cycles>0) {
244     if (cycles<=thisctr.count_binary) {
245       thisctr.count_binary-=cycles;
246       cycles-=cycles;
247       set_count_to_binary(thisctr);
248     } else {
249       cycles-=(thisctr.count_binary+1);
250       thisctr.count_binary-=thisctr.count_binary;
251       set_count_to_binary(thisctr);
252       decrement(thisctr);
253     }
254   }
255 }
256 
clock_multiple(Bit8u cnum,Bit32u cycles)257 void pit_82C54::clock_multiple(Bit8u cnum, Bit32u cycles)
258 {
259   if (cnum>MAX_COUNTER) {
260     BX_ERROR(("Counter number too high in clock"));
261   } else {
262     counter_type &thisctr = counter[cnum];
263     while(cycles>0) {
264       if (thisctr.next_change_time==0) {
265         if (thisctr.count_written) {
266           switch(thisctr.mode) {
267           case 0:
268             if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
269               decrement_multiple(thisctr, cycles);
270             }
271             break;
272           case 1:
273             decrement_multiple(thisctr, cycles);
274             break;
275           case 2:
276             if (!thisctr.first_pass && thisctr.GATE) {
277               decrement_multiple(thisctr, cycles);
278             }
279             break;
280           case 3:
281             if (!thisctr.first_pass && thisctr.GATE) {
282               decrement_multiple(thisctr, 2*cycles);
283             }
284             break;
285           case 4:
286             if (thisctr.GATE) {
287               decrement_multiple(thisctr, cycles);
288             }
289             break;
290           case 5:
291             decrement_multiple(thisctr, cycles);
292             break;
293           default:
294             break;
295           }
296         }
297         cycles-=cycles;
298       } else {
299         switch(thisctr.mode) {
300         case 0:
301         case 1:
302         case 2:
303         case 4:
304         case 5:
305           if (thisctr.next_change_time > cycles) {
306             decrement_multiple(thisctr,cycles);
307             thisctr.next_change_time-=cycles;
308             cycles-=cycles;
309           } else {
310             decrement_multiple(thisctr,(thisctr.next_change_time-1));
311             cycles-=thisctr.next_change_time;
312             clock(cnum);
313           }
314           break;
315         case 3:
316           if (thisctr.next_change_time > cycles) {
317             decrement_multiple(thisctr,cycles*2);
318             thisctr.next_change_time-=cycles;
319             cycles-=cycles;
320           } else {
321             decrement_multiple(thisctr,(thisctr.next_change_time-1)*2);
322             cycles-=thisctr.next_change_time;
323             clock(cnum);
324           }
325           break;
326         default:
327           cycles-=cycles;
328           break;
329         }
330       }
331     }
332   }
333 }
334 
clock(Bit8u cnum)335 void BX_CPP_AttrRegparmN(1) pit_82C54::clock(Bit8u cnum)
336 {
337     if (cnum>MAX_COUNTER) {
338       BX_ERROR(("Counter number too high in clock"));
339     } else {
340       counter_type &thisctr = counter[cnum];
341       switch(thisctr.mode) {
342       case 0:
343         if (thisctr.count_written) {
344           if (thisctr.null_count) {
345             set_count(thisctr, thisctr.inlatch);
346             if (thisctr.GATE) {
347               if (thisctr.count_binary==0) {
348                 thisctr.next_change_time=1;
349               } else {
350                 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
351               }
352             } else {
353               thisctr.next_change_time=0;
354             }
355             thisctr.null_count=0;
356           } else {
357             if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
358               decrement(thisctr);
359               if (!thisctr.OUTpin) {
360                 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
361                 if (!thisctr.count) {
362                   set_OUT(thisctr,1);
363                 }
364               } else {
365                 thisctr.next_change_time=0;
366               }
367             } else {
368               thisctr.next_change_time=0; //if the clock isn't moving.
369             }
370           }
371         } else {
372           thisctr.next_change_time=0; //default to 0.
373         }
374         thisctr.triggerGATE=0;
375         break;
376       case 1:
377         if (thisctr.count_written) {
378           if (thisctr.triggerGATE) {
379             set_count(thisctr, thisctr.inlatch);
380             if (thisctr.count_binary==0) {
381               thisctr.next_change_time=1;
382             } else {
383               thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
384             }
385             thisctr.null_count=0;
386             set_OUT(thisctr,0);
387             if (thisctr.write_state==MSByte_multiple) {
388               BX_ERROR(("Undefined behavior when loading a half loaded count."));
389             }
390           } else {
391             decrement(thisctr);
392             if (!thisctr.OUTpin) {
393               if (thisctr.count_binary==0) {
394                 thisctr.next_change_time=1;
395               } else {
396                 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
397               }
398               if (thisctr.count==0) {
399                 set_OUT(thisctr,1);
400               }
401             } else {
402               thisctr.next_change_time=0;
403             }
404           }
405         } else {
406           thisctr.next_change_time=0; //default to 0.
407         }
408         thisctr.triggerGATE=0;
409         break;
410       case 2:
411         if (thisctr.count_written) {
412           if (thisctr.triggerGATE || thisctr.first_pass) {
413             set_count(thisctr, thisctr.inlatch);
414             thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF;
415             thisctr.null_count=0;
416             if (thisctr.inlatch==1) {
417               BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2."));
418             }
419             if (!thisctr.OUTpin) {
420               set_OUT(thisctr,1);
421             }
422             if (thisctr.write_state==MSByte_multiple) {
423               BX_ERROR(("Undefined behavior when loading a half loaded count."));
424             }
425             thisctr.first_pass=0;
426           } else {
427             if (thisctr.GATE) {
428               decrement(thisctr);
429               thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF;
430               if (thisctr.count==1) {
431                 thisctr.next_change_time=1;
432                 set_OUT(thisctr,0);
433                 thisctr.first_pass=1;
434               }
435             } else {
436               thisctr.next_change_time=0;
437             }
438           }
439         } else {
440           thisctr.next_change_time=0;
441         }
442         thisctr.triggerGATE=0;
443         break;
444       case 3:
445         if (thisctr.count_written) {
446           if ((thisctr.triggerGATE || thisctr.first_pass
447              || thisctr.state_bit_2) && thisctr.GATE) {
448             set_count(thisctr, thisctr.inlatch & 0xFFFE);
449             thisctr.state_bit_1=thisctr.inlatch & 0x1;
450             if (!thisctr.OUTpin || !thisctr.state_bit_1) {
451               if (((thisctr.count_binary/2)-1)==0) {
452                 thisctr.next_change_time=1;
453               } else {
454                 thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
455               }
456             } else {
457               if ((thisctr.count_binary/2)==0) {
458                 thisctr.next_change_time=1;
459               } else {
460                 thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF;
461               }
462             }
463             thisctr.null_count=0;
464             if (thisctr.inlatch==1) {
465               BX_ERROR(("Count of 1 is invalid in pit mode 3."));
466             }
467             if (!thisctr.OUTpin) {
468               set_OUT(thisctr,1);
469             } else if (thisctr.OUTpin && !thisctr.first_pass) {
470               set_OUT(thisctr,0);
471             }
472             if (thisctr.write_state==MSByte_multiple) {
473               BX_ERROR(("Undefined behavior when loading a half loaded count."));
474             }
475             thisctr.state_bit_2=0;
476             thisctr.first_pass=0;
477           } else {
478             if (thisctr.GATE) {
479               decrement(thisctr);
480               decrement(thisctr);
481               if (!thisctr.OUTpin || !thisctr.state_bit_1) {
482                 thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
483               } else {
484                 thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF;
485               }
486               if (thisctr.count==0) {
487                 thisctr.state_bit_2=1;
488                 thisctr.next_change_time=1;
489               }
490               if ((thisctr.count==2) &&
491                  (!thisctr.OUTpin || !thisctr.state_bit_1))
492               {
493                 thisctr.state_bit_2=1;
494                 thisctr.next_change_time=1;
495               }
496             } else {
497               thisctr.next_change_time=0;
498             }
499           }
500         } else {
501           thisctr.next_change_time=0;
502         }
503         thisctr.triggerGATE=0;
504         break;
505       case 4:
506         if (thisctr.count_written) {
507           if (!thisctr.OUTpin) {
508             set_OUT(thisctr,1);
509           }
510           if (thisctr.null_count) {
511             set_count(thisctr, thisctr.inlatch);
512             if (thisctr.GATE) {
513               if (thisctr.count_binary==0) {
514                 thisctr.next_change_time=1;
515               } else {
516                 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
517               }
518             } else {
519               thisctr.next_change_time=0;
520             }
521             thisctr.null_count=0;
522             if (thisctr.write_state==MSByte_multiple) {
523               BX_ERROR(("Undefined behavior when loading a half loaded count."));
524             }
525             thisctr.first_pass=1;
526           } else {
527             if (thisctr.GATE) {
528               decrement(thisctr);
529               if (thisctr.first_pass) {
530                 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
531                 if (!thisctr.count) {
532                   set_OUT(thisctr,0);
533                   thisctr.next_change_time=1;
534                   thisctr.first_pass=0;
535                 }
536               } else {
537                 thisctr.next_change_time=0;
538               }
539             } else {
540               thisctr.next_change_time=0;
541             }
542           }
543         } else {
544           thisctr.next_change_time=0;
545         }
546         thisctr.triggerGATE=0;
547         break;
548       case 5:
549         if (thisctr.count_written) {
550           if (!thisctr.OUTpin) {
551             set_OUT(thisctr,1);
552           }
553           if (thisctr.triggerGATE) {
554             set_count(thisctr, thisctr.inlatch);
555             if (thisctr.count_binary==0) {
556               thisctr.next_change_time=1;
557             } else {
558               thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
559             }
560             thisctr.null_count=0;
561             if (thisctr.write_state==MSByte_multiple) {
562               BX_ERROR(("Undefined behavior when loading a half loaded count."));
563             }
564             thisctr.first_pass=1;
565           } else {
566             decrement(thisctr);
567             if (thisctr.first_pass) {
568               thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
569               if (!thisctr.count) {
570                 set_OUT(thisctr,0);
571                 thisctr.next_change_time=1;
572                 thisctr.first_pass=0;
573               }
574             } else {
575               thisctr.next_change_time=0;
576             }
577           }
578         } else {
579           thisctr.next_change_time=0;
580         }
581         thisctr.triggerGATE=0;
582         break;
583       default:
584         BX_ERROR(("Mode not implemented."));
585         thisctr.next_change_time=0;
586         thisctr.triggerGATE=0;
587         break;
588       }
589     }
590 }
591 
clock_all(Bit32u cycles)592 void pit_82C54::clock_all(Bit32u cycles)
593 {
594     BX_DEBUG(("clock_all:  cycles=%d",cycles));
595     clock_multiple(0,cycles);
596     clock_multiple(1,cycles);
597     clock_multiple(2,cycles);
598 }
599 
read(Bit8u address)600 Bit8u pit_82C54::read(Bit8u address)
601 {
602     if (address>MAX_ADDRESS) {
603       BX_ERROR(("Counter address incorrect in data read."));
604     } else if (address==CONTROL_ADDRESS) {
605       BX_DEBUG(("PIT Read: Control Word Register."));
606       //Read from control word register;
607       /* This might be okay.  If so, 0 seems the most logical
608        *  return value from looking at the docs.
609        */
610       BX_ERROR(("Read from control word register not defined."));
611       return 0;
612     } else {
613       //Read from a counter;
614       BX_DEBUG(("PIT Read: Counter %d.",address));
615       counter_type &thisctr=counter[address];
616       if (thisctr.status_latched) {
617         //Latched Status Read;
618         if (thisctr.count_MSB_latched &&
619           (thisctr.read_state==MSByte_multiple)) {
620           BX_ERROR(("Undefined output when status latched and count half read."));
621         } else {
622           thisctr.status_latched=0;
623           return thisctr.status_latch;
624         }
625       } else {
626         //Latched Count Read;
627         if (thisctr.count_LSB_latched) {
628           //Read Least Significant Byte;
629           if (thisctr.read_state==LSByte_multiple) {
630             BX_DEBUG(("Setting read_state to MSB_mult"));
631             thisctr.read_state=MSByte_multiple;
632           }
633           thisctr.count_LSB_latched=0;
634           return (thisctr.outlatch & 0xFF);
635         } else if (thisctr.count_MSB_latched) {
636           //Read Most Significant Byte;
637           if (thisctr.read_state==MSByte_multiple) {
638             BX_DEBUG(("Setting read_state to LSB_mult"));
639             thisctr.read_state=LSByte_multiple;
640           }
641           thisctr.count_MSB_latched=0;
642           return ((thisctr.outlatch>>8) & 0xFF);
643         } else {
644           //Unlatched Count Read;
645           if (!(thisctr.read_state & 0x1)) {
646             //Read Least Significant Byte;
647             if (thisctr.read_state==LSByte_multiple) {
648               thisctr.read_state=MSByte_multiple;
649               BX_DEBUG(("Setting read_state to MSB_mult"));
650             }
651             return (thisctr.count & 0xFF);
652           } else {
653             //Read Most Significant Byte;
654             if (thisctr.read_state==MSByte_multiple) {
655               BX_DEBUG(("Setting read_state to LSB_mult"));
656               thisctr.read_state=LSByte_multiple;
657             }
658             return ((thisctr.count>>8) & 0xFF);
659           }
660         }
661       }
662     }
663 
664     //Should only get here on errors;
665     return 0;
666 }
667 
write(Bit8u address,Bit8u data)668 void pit_82C54::write(Bit8u address, Bit8u data)
669 {
670     if (address>MAX_ADDRESS) {
671       BX_ERROR(("Counter address incorrect in data write."));
672     } else if (address==CONTROL_ADDRESS) {
673       Bit8u SC, RW, M, BCD;
674       controlword=data;
675       BX_DEBUG(("Control Word Write."));
676       SC = (controlword>>6) & 0x3;
677       RW = (controlword>>4) & 0x3;
678       M = (controlword>>1) & 0x7;
679       BCD = controlword & 0x1;
680       if (SC == 3) {
681         //READ_BACK command;
682         int i;
683         BX_DEBUG(("READ_BACK command."));
684         for(i=0;i<=MAX_COUNTER;i++) {
685           if ((M>>i) & 0x1) {
686             //If we are using this counter;
687             counter_type &thisctr=counter[i];
688             if (!((controlword>>5) & 1)) {
689               //Latch Count;
690               latch_counter(thisctr);
691             }
692             if (!((controlword>>4) & 1)) {
693               //Latch Status;
694               if (thisctr.status_latched) {
695                 //Do nothing because latched status has not been read.;
696               } else {
697                 thisctr.status_latch=
698                   ((thisctr.OUTpin & 0x1) << 7) |
699                   ((thisctr.null_count & 0x1) << 6) |
700                   ((thisctr.rw_mode & 0x3) << 4) |
701                   ((thisctr.mode & 0x7) << 1) |
702                   (thisctr.bcd_mode&0x1);
703                 thisctr.status_latched=1;
704               }
705             }
706           }
707         }
708       } else {
709         counter_type &thisctr = counter[SC];
710         if (!RW) {
711           //Counter Latch command;
712           BX_DEBUG(("Counter Latch command.  SC=%d",SC));
713           latch_counter(thisctr);
714         } else {
715           //Counter Program Command;
716           BX_DEBUG(("Counter Program command.  SC=%d, RW=%d, M=%d, BCD=%d",SC,RW,M,BCD));
717           thisctr.null_count=1;
718           thisctr.count_LSB_latched=0;
719           thisctr.count_MSB_latched=0;
720           thisctr.status_latched=0;
721           thisctr.inlatch=0;
722           thisctr.count_written=0;
723           thisctr.first_pass=1;
724           thisctr.rw_mode=RW;
725           thisctr.bcd_mode=(BCD > 0);
726           thisctr.mode=M;
727           switch(RW) {
728           case 0x1:
729             BX_DEBUG(("Setting read_state to LSB"));
730             thisctr.read_state=LSByte;
731             thisctr.write_state=LSByte;
732             break;
733           case 0x2:
734             BX_DEBUG(("Setting read_state to MSB"));
735             thisctr.read_state=MSByte;
736             thisctr.write_state=MSByte;
737             break;
738           case 0x3:
739             BX_DEBUG(("Setting read_state to LSB_mult"));
740             thisctr.read_state=LSByte_multiple;
741             thisctr.write_state=LSByte_multiple;
742             break;
743           default:
744             BX_ERROR(("RW field invalid in control word write."));
745             break;
746           }
747           //All modes except mode 0 have initial output of 1.;
748           if (M) {
749             set_OUT(thisctr, 1);
750           } else {
751             set_OUT(thisctr, 0);
752           }
753           thisctr.next_change_time=0;
754         }
755       }
756     } else {
757       //Write to counter initial value.
758       counter_type &thisctr = counter[address];
759       BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address,data));
760       switch(thisctr.write_state) {
761       case LSByte_multiple:
762         thisctr.inlatch = data;
763         thisctr.write_state = MSByte_multiple;
764         break;
765       case LSByte:
766         thisctr.inlatch = data;
767         thisctr.count_written = 1;
768         break;
769       case MSByte_multiple:
770         thisctr.write_state = LSByte_multiple;
771         thisctr.inlatch |= (data << 8);
772         thisctr.count_written = 1;
773         break;
774       case MSByte:
775         thisctr.inlatch = (data << 8);
776         thisctr.count_written = 1;
777         break;
778       default:
779         BX_ERROR(("write counter in invalid write state."));
780         break;
781       }
782       if (thisctr.count_written && thisctr.write_state != MSByte_multiple) {
783         thisctr.null_count = 1;
784         set_count(thisctr, thisctr.inlatch);
785       }
786       switch(thisctr.mode) {
787       case 0:
788         if (thisctr.write_state==MSByte_multiple) {
789           set_OUT(thisctr,0);
790         }
791         thisctr.next_change_time=1;
792         break;
793       case 1:
794         if (thisctr.triggerGATE) { //for initial writes, if already saw trigger.
795           thisctr.next_change_time=1;
796         } //Otherwise, no change.
797         break;
798       case 6:
799       case 2:
800         thisctr.next_change_time=1; //FIXME: this could be loosened.
801         break;
802       case 7:
803       case 3:
804         thisctr.next_change_time=1; //FIXME: this could be loosened.
805         break;
806       case 4:
807         thisctr.next_change_time=1;
808         break;
809       case 5:
810         if (thisctr.triggerGATE) { //for initial writes, if already saw trigger.
811           thisctr.next_change_time=1;
812         } //Otherwise, no change.
813         break;
814       }
815     }
816 }
817 
set_GATE(Bit8u cnum,bool data)818 void pit_82C54::set_GATE(Bit8u cnum, bool data)
819 {
820   if (cnum>MAX_COUNTER) {
821     BX_ERROR(("Counter number incorrect in 82C54 set_GATE"));
822   } else {
823     counter_type &thisctr = counter[cnum];
824     if (!((thisctr.GATE&&data) || (!(thisctr.GATE||data)))) {
825       BX_DEBUG(("Changing GATE %d to: %d",cnum,data));
826       thisctr.GATE=data;
827       if (thisctr.GATE) {
828         thisctr.triggerGATE=1;
829       }
830       switch(thisctr.mode) {
831         case 0:
832           if (data && thisctr.count_written) {
833             if (thisctr.null_count) {
834               thisctr.next_change_time=1;
835             } else {
836               if ((!thisctr.OUTpin) &&
837                    (thisctr.write_state!=MSByte_multiple))
838               {
839                 if (thisctr.count_binary==0) {
840                   thisctr.next_change_time=1;
841                 } else {
842                   thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
843                 }
844               } else {
845                 thisctr.next_change_time=0;
846               }
847             }
848           } else {
849             if (thisctr.null_count) {
850               thisctr.next_change_time=1;
851             } else {
852               thisctr.next_change_time=0;
853             }
854           }
855           break;
856         case 1:
857           if (data && thisctr.count_written) { //only triggers cause a change.
858             thisctr.next_change_time=1;
859           }
860           break;
861         case 2:
862           if (!data) {
863             set_OUT(thisctr,1);
864             thisctr.next_change_time=0;
865           } else {
866             if (thisctr.count_written) {
867               thisctr.next_change_time=1;
868             } else {
869               thisctr.next_change_time=0;
870             }
871           }
872           break;
873         case 3:
874           if (!data) {
875             set_OUT(thisctr,1);
876             thisctr.first_pass=1;
877             thisctr.next_change_time=0;
878           } else {
879             if (thisctr.count_written) {
880               thisctr.next_change_time=1;
881             } else {
882               thisctr.next_change_time=0;
883             }
884           }
885           break;
886         case 4:
887           if (!thisctr.OUTpin || thisctr.null_count) {
888             thisctr.next_change_time=1;
889           } else {
890             if (data && thisctr.count_written) {
891               if (thisctr.first_pass) {
892                 if (thisctr.count_binary==0) {
893                   thisctr.next_change_time=1;
894                 } else {
895                   thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
896                 }
897               } else {
898                 thisctr.next_change_time=0;
899               }
900             } else {
901               thisctr.next_change_time=0;
902             }
903           }
904           break;
905         case 5:
906           if (data && thisctr.count_written) { //only triggers cause a change.
907             thisctr.next_change_time=1;
908           }
909           break;
910         default:
911           break;
912       }
913     }
914   }
915 }
916 
read_OUT(Bit8u cnum)917 bool pit_82C54::read_OUT(Bit8u cnum)
918 {
919   if (cnum>MAX_COUNTER) {
920     BX_ERROR(("Counter number incorrect in 82C54 read_OUT"));
921     return 0;
922   }
923 
924   return counter[cnum].OUTpin;
925 }
926 
read_GATE(Bit8u cnum)927 bool pit_82C54::read_GATE(Bit8u cnum)
928 {
929   if (cnum>MAX_COUNTER) {
930     BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
931     return 0;
932   }
933 
934   return counter[cnum].GATE;
935 }
936 
get_clock_event_time(Bit8u cnum)937 Bit32u pit_82C54::get_clock_event_time(Bit8u cnum)
938 {
939   if (cnum>MAX_COUNTER) {
940     BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
941     return 0;
942   }
943 
944   return counter[cnum].next_change_time;
945 }
946 
get_next_event_time(void)947 Bit32u pit_82C54::get_next_event_time(void)
948 {
949   Bit32u time0=get_clock_event_time(0);
950   Bit32u time1=get_clock_event_time(1);
951   Bit32u time2=get_clock_event_time(2);
952 
953   Bit32u out=time0;
954   if (time1 && (time1<out))
955     out=time1;
956   if (time2 && (time2<out))
957     out=time2;
958   return out;
959 }
960 
get_inlatch(int counternum)961 Bit16u pit_82C54::get_inlatch(int counternum)
962 {
963   return counter[counternum].inlatch;
964 }
965 
new_count_ready(int countnum)966 bool pit_82C54::new_count_ready(int countnum)
967 {
968   return (counter[countnum].write_state != MSByte_multiple);
969 }
970 
get_mode(int countnum)971 Bit8u pit_82C54::get_mode(int countnum)
972 {
973   return counter[countnum].mode;
974 }
975 
set_OUT_handler(Bit8u counternum,out_handler_t outh)976 void pit_82C54::set_OUT_handler(Bit8u counternum, out_handler_t outh)
977 {
978   counter[counternum].out_handler = outh;
979 }
980