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