1 /////////////////////////////////////////////////////////////////////////
2 // $Id: pit82c54.cc,v 1.32 2008/02/15 22:05:43 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
6 * Emulator of an Intel 8254/82C54 Programmable Interval Timer.
7 * Greg Alexander <yakovlev@usa.com>
10 * Things I am unclear on (greg):
11 * 1.)What happens if both the status and count registers are latched,
12 * but the first of the two count registers has already been read?
14 * latch count 0 (16-bit)
15 * Read count 0 (read LSByte)
16 * READ_BACK status of count 0
17 * Read count 0 - do you get MSByte or status?
18 * This will be flagged as an error.
19 * 2.)What happens when we latch the output in the middle of a 2-part
21 * 3.)I assumed that programming a counter removes a latched status.
22 * 4.)I implemented the 8254 description of mode 0, not the 82C54 one.
23 * 5.)clock() calls represent a rising clock edge followed by a falling
25 * 6.)What happens when we trigger mode 1 in the middle of a 2-part
31 #define LOG_THIS this->
34 void pit_82C54::print_counter(counter_type
&thisctr
)
36 BX_INFO(("Printing Counter"));
37 BX_INFO(("count: %d",thisctr
.count
));
38 BX_INFO(("count_binary: %x",thisctr
.count_binary
));
39 BX_INFO(("counter gate: %x",thisctr
.GATE
));
40 BX_INFO(("counter OUT: %x",thisctr
.OUTpin
));
41 BX_INFO(("next_change_time: %d",thisctr
.next_change_time
));
42 BX_INFO(("End Counter Printout"));
45 void pit_82C54::print_cnum(Bit8u cnum
)
47 if (cnum
>MAX_COUNTER
) {
48 BX_ERROR(("Bad counter index to print_cnum"));
50 print_counter(counter
[cnum
]);
54 void pit_82C54::latch_counter(counter_type
&thisctr
)
56 if (thisctr
.count_LSB_latched
|| thisctr
.count_MSB_latched
) {
57 //Do nothing because previous latch has not been read.;
59 switch(thisctr
.read_state
) {
61 thisctr
.outlatch
=thisctr
.count
& 0xFFFF;
62 thisctr
.count_MSB_latched
=1;
65 thisctr
.outlatch
=thisctr
.count
& 0xFFFF;
66 thisctr
.count_LSB_latched
=1;
69 thisctr
.outlatch
=thisctr
.count
& 0xFFFF;
70 thisctr
.count_LSB_latched
=1;
71 thisctr
.count_MSB_latched
=1;
74 if (!(seen_problems
& UNL_2P_READ
)) {
75 // seen_problems|=UNL_2P_READ;
76 BX_ERROR(("Unknown behavior when latching during 2-part read."));
77 BX_ERROR((" This message will not be repeated."));
79 //I guess latching and resetting to LSB first makes sense;
80 BX_DEBUG(("Setting read_state to LSB_mult"));
81 thisctr
.read_state
=LSByte_multiple
;
82 thisctr
.outlatch
=thisctr
.count
& 0xFFFF;
83 thisctr
.count_LSB_latched
=1;
84 thisctr
.count_MSB_latched
=1;
87 BX_ERROR(("Unknown read mode found during latch command."));
93 void pit_82C54::set_OUT (counter_type
&thisctr
, bx_bool data
)
95 if (thisctr
.OUTpin
!= data
) {
96 thisctr
.OUTpin
= data
;
97 if (thisctr
.out_handler
!= NULL
) {
98 thisctr
.out_handler(data
);
103 void BX_CPP_AttrRegparmN(2)
104 pit_82C54::set_count (counter_type
&thisctr
, Bit32u data
)
106 thisctr
.count
=data
& 0xFFFF;
107 set_binary_to_count(thisctr
);
110 void BX_CPP_AttrRegparmN(1)
111 pit_82C54::set_count_to_binary(counter_type
&thisctr
)
113 if (thisctr
.bcd_mode
) {
115 (((thisctr
.count_binary
/1)%10)<<0) |
116 (((thisctr
.count_binary
/10)%10)<<4) |
117 (((thisctr
.count_binary
/100)%10)<<8) |
118 (((thisctr
.count_binary
/1000)%10)<<12);
120 thisctr
.count
=thisctr
.count_binary
;
124 void BX_CPP_AttrRegparmN(1)
125 pit_82C54::set_binary_to_count(counter_type
&thisctr
)
127 if (thisctr
.bcd_mode
) {
128 thisctr
.count_binary
=
129 (1*((thisctr
.count
>>0)&0xF)) +
130 (10*((thisctr
.count
>>4)&0xF)) +
131 (100*((thisctr
.count
>>8)&0xF)) +
132 (1000*((thisctr
.count
>>12)&0xF));
134 thisctr
.count_binary
=thisctr
.count
;
138 void BX_CPP_AttrRegparmN(1)
139 pit_82C54::decrement (counter_type
&thisctr
)
141 if (!thisctr
.count
) {
142 if (thisctr
.bcd_mode
) {
143 thisctr
.count
=0x9999;
144 thisctr
.count_binary
=9999;
146 thisctr
.count
=0xFFFF;
147 thisctr
.count_binary
=0xFFFF;
150 thisctr
.count_binary
--;
151 set_count_to_binary(thisctr
);
155 void pit_82C54::init(void)
160 for(int i
=0;i
<3;i
++) {
161 BX_DEBUG(("Setting read_state to LSB"));
162 counter
[i
].read_state
=LSByte
;
163 counter
[i
].write_state
=LSByte
;
166 counter
[i
].triggerGATE
=0;
168 counter
[i
].first_pass
=0;
169 counter
[i
].bcd_mode
=0;
171 counter
[i
].count_binary
=0;
172 counter
[i
].state_bit_1
=0;
173 counter
[i
].state_bit_2
=0;
174 counter
[i
].null_count
=0;
175 counter
[i
].rw_mode
=1;
176 counter
[i
].count_written
=1;
177 counter
[i
].count_LSB_latched
=0;
178 counter
[i
].count_MSB_latched
=0;
179 counter
[i
].status_latched
=0;
180 counter
[i
].next_change_time
=0;
181 counter
[i
].out_handler
=NULL
;
186 pit_82C54::pit_82C54(void)
191 void pit_82C54::reset(unsigned type
) {}
193 void pit_82C54::register_state(bx_param_c
*parent
)
197 for (unsigned i
=0; i
<3; i
++) {
198 sprintf(name
, "%d", i
);
199 bx_list_c
*tim
= new bx_list_c(parent
, name
, 22);
200 new bx_shadow_bool_c(tim
, "GATE", &counter
[i
].GATE
);
201 new bx_shadow_bool_c(tim
, "OUTpin", &counter
[i
].OUTpin
);
202 new bx_shadow_num_c(tim
, "count", &counter
[i
].count
);
203 new bx_shadow_num_c(tim
, "outlatch", &counter
[i
].outlatch
);
204 new bx_shadow_num_c(tim
, "inlatch", &counter
[i
].inlatch
);
205 new bx_shadow_num_c(tim
, "status_latch", &counter
[i
].status_latch
);
206 new bx_shadow_num_c(tim
, "rw_mode", &counter
[i
].rw_mode
);
207 new bx_shadow_num_c(tim
, "mode", &counter
[i
].mode
);
208 new bx_shadow_bool_c(tim
, "bcd_mode", &counter
[i
].bcd_mode
);
209 new bx_shadow_bool_c(tim
, "null_count", &counter
[i
].null_count
);
210 new bx_shadow_bool_c(tim
, "count_LSB_latched", &counter
[i
].count_LSB_latched
);
211 new bx_shadow_bool_c(tim
, "count_MSB_latched", &counter
[i
].count_MSB_latched
);
212 new bx_shadow_bool_c(tim
, "status_latched", &counter
[i
].status_latched
);
213 new bx_shadow_num_c(tim
, "count_binary", &counter
[i
].count_binary
);
214 new bx_shadow_bool_c(tim
, "triggerGATE", &counter
[i
].triggerGATE
);
215 new bx_shadow_num_c(tim
, "write_state", (Bit8u
*)&counter
[i
].write_state
);
216 new bx_shadow_num_c(tim
, "read_state", (Bit8u
*)&counter
[i
].read_state
);
217 new bx_shadow_bool_c(tim
, "count_written", &counter
[i
].count_written
);
218 new bx_shadow_bool_c(tim
, "first_pass", &counter
[i
].first_pass
);
219 new bx_shadow_bool_c(tim
, "state_bit_1", &counter
[i
].state_bit_1
);
220 new bx_shadow_bool_c(tim
, "state_bit_2", &counter
[i
].state_bit_2
);
221 new bx_shadow_num_c(tim
, "next_change_time", &counter
[i
].next_change_time
);
225 void BX_CPP_AttrRegparmN(2)
226 pit_82C54::decrement_multiple(counter_type
&thisctr
, Bit32u cycles
)
229 if (cycles
<=thisctr
.count_binary
) {
230 thisctr
.count_binary
-=cycles
;
232 set_count_to_binary(thisctr
);
234 cycles
-=(thisctr
.count_binary
+1);
235 thisctr
.count_binary
-=thisctr
.count_binary
;
236 set_count_to_binary(thisctr
);
242 void pit_82C54::clock_multiple(Bit8u cnum
, Bit32u cycles
)
244 if (cnum
>MAX_COUNTER
) {
245 BX_ERROR(("Counter number too high in clock"));
247 counter_type
&thisctr
= counter
[cnum
];
249 if (thisctr
.next_change_time
==0) {
250 if (thisctr
.count_written
) {
251 switch(thisctr
.mode
) {
253 if (thisctr
.GATE
&& (thisctr
.write_state
!=MSByte_multiple
)) {
254 decrement_multiple(thisctr
, cycles
);
258 decrement_multiple(thisctr
, cycles
);
261 if (!thisctr
.first_pass
&& thisctr
.GATE
) {
262 decrement_multiple(thisctr
, cycles
);
266 if (!thisctr
.first_pass
&& thisctr
.GATE
) {
267 decrement_multiple(thisctr
, 2*cycles
);
272 decrement_multiple(thisctr
, cycles
);
276 decrement_multiple(thisctr
, cycles
);
284 switch(thisctr
.mode
) {
290 if (thisctr
.next_change_time
> cycles
) {
291 decrement_multiple(thisctr
,cycles
);
292 thisctr
.next_change_time
-=cycles
;
295 decrement_multiple(thisctr
,(thisctr
.next_change_time
-1));
296 cycles
-=thisctr
.next_change_time
;
301 if (thisctr
.next_change_time
> cycles
) {
302 decrement_multiple(thisctr
,cycles
*2);
303 thisctr
.next_change_time
-=cycles
;
306 decrement_multiple(thisctr
,(thisctr
.next_change_time
-1)*2);
307 cycles
-=thisctr
.next_change_time
;
318 print_counter(thisctr
);
323 void BX_CPP_AttrRegparmN(1)
324 pit_82C54::clock(Bit8u cnum
)
326 if (cnum
>MAX_COUNTER
) {
327 BX_ERROR(("Counter number too high in clock"));
329 counter_type
&thisctr
= counter
[cnum
];
330 switch(thisctr
.mode
) {
332 if (thisctr
.count_written
) {
333 if (thisctr
.null_count
) {
334 set_count(thisctr
, thisctr
.inlatch
);
336 if (thisctr
.count_binary
==0) {
337 thisctr
.next_change_time
=1;
339 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
342 thisctr
.next_change_time
=0;
344 thisctr
.null_count
=0;
346 if (thisctr
.GATE
&& (thisctr
.write_state
!=MSByte_multiple
)) {
348 if (!thisctr
.OUTpin
) {
349 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
350 if (!thisctr
.count
) {
354 thisctr
.next_change_time
=0;
357 thisctr
.next_change_time
=0; //if the clock isn't moving.
361 thisctr
.next_change_time
=0; //default to 0.
363 thisctr
.triggerGATE
=0;
366 if (thisctr
.count_written
) {
367 if (thisctr
.triggerGATE
) {
368 set_count(thisctr
, thisctr
.inlatch
);
369 if (thisctr
.count_binary
==0) {
370 thisctr
.next_change_time
=1;
372 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
374 thisctr
.null_count
=0;
376 if (thisctr
.write_state
==MSByte_multiple
) {
377 BX_ERROR(("Undefined behavior when loading a half loaded count."));
381 if (!thisctr
.OUTpin
) {
382 if (thisctr
.count_binary
==0) {
383 thisctr
.next_change_time
=1;
385 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
387 if (thisctr
.count
==0) {
391 thisctr
.next_change_time
=0;
395 thisctr
.next_change_time
=0; //default to 0.
397 thisctr
.triggerGATE
=0;
400 if (thisctr
.count_written
) {
401 if (thisctr
.triggerGATE
|| thisctr
.first_pass
) {
402 set_count(thisctr
, thisctr
.inlatch
);
403 thisctr
.next_change_time
=(thisctr
.count_binary
-1) & 0xFFFF;
404 thisctr
.null_count
=0;
405 if (thisctr
.inlatch
==1) {
406 BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2."));
408 if (!thisctr
.OUTpin
) {
411 if (thisctr
.write_state
==MSByte_multiple
) {
412 BX_ERROR(("Undefined behavior when loading a half loaded count."));
414 thisctr
.first_pass
=0;
418 thisctr
.next_change_time
=(thisctr
.count_binary
-1) & 0xFFFF;
419 if (thisctr
.count
==1) {
420 thisctr
.next_change_time
=1;
422 thisctr
.first_pass
=1;
425 thisctr
.next_change_time
=0;
429 thisctr
.next_change_time
=0;
431 thisctr
.triggerGATE
=0;
434 if (thisctr
.count_written
) {
435 if ((thisctr
.triggerGATE
|| thisctr
.first_pass
436 || thisctr
.state_bit_2
) && thisctr
.GATE
) {
437 set_count(thisctr
, thisctr
.inlatch
& 0xFFFE);
438 thisctr
.state_bit_1
=thisctr
.inlatch
& 0x1;
439 if (!thisctr
.OUTpin
|| !thisctr
.state_bit_1
) {
440 if (((thisctr
.count_binary
/2)-1)==0) {
441 thisctr
.next_change_time
=1;
443 thisctr
.next_change_time
=((thisctr
.count_binary
/2)-1) & 0xFFFF;
446 if ((thisctr
.count_binary
/2)==0) {
447 thisctr
.next_change_time
=1;
449 thisctr
.next_change_time
=(thisctr
.count_binary
/2) & 0xFFFF;
452 thisctr
.null_count
=0;
453 if (thisctr
.inlatch
==1) {
454 BX_ERROR(("Count of 1 is invalid in pit mode 3."));
456 if (!thisctr
.OUTpin
) {
458 } else if (thisctr
.OUTpin
&& !thisctr
.first_pass
) {
461 if (thisctr
.write_state
==MSByte_multiple
) {
462 BX_ERROR(("Undefined behavior when loading a half loaded count."));
464 thisctr
.state_bit_2
=0;
465 thisctr
.first_pass
=0;
470 if (!thisctr
.OUTpin
|| !thisctr
.state_bit_1
) {
471 thisctr
.next_change_time
=((thisctr
.count_binary
/2)-1) & 0xFFFF;
473 thisctr
.next_change_time
=(thisctr
.count_binary
/2) & 0xFFFF;
475 if (thisctr
.count
==0) {
476 thisctr
.state_bit_2
=1;
477 thisctr
.next_change_time
=1;
479 if ((thisctr
.count
==2) &&
480 (!thisctr
.OUTpin
|| !thisctr
.state_bit_1
))
482 thisctr
.state_bit_2
=1;
483 thisctr
.next_change_time
=1;
486 thisctr
.next_change_time
=0;
490 thisctr
.next_change_time
=0;
492 thisctr
.triggerGATE
=0;
495 if (thisctr
.count_written
) {
496 if (!thisctr
.OUTpin
) {
499 if (thisctr
.null_count
) {
500 set_count(thisctr
, thisctr
.inlatch
);
502 if (thisctr
.count_binary
==0) {
503 thisctr
.next_change_time
=1;
505 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
508 thisctr
.next_change_time
=0;
510 thisctr
.null_count
=0;
511 if (thisctr
.write_state
==MSByte_multiple
) {
512 BX_ERROR(("Undefined behavior when loading a half loaded count."));
514 thisctr
.first_pass
=1;
518 if (thisctr
.first_pass
) {
519 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
520 if (!thisctr
.count
) {
522 thisctr
.next_change_time
=1;
523 thisctr
.first_pass
=0;
526 thisctr
.next_change_time
=0;
529 thisctr
.next_change_time
=0;
533 thisctr
.next_change_time
=0;
535 thisctr
.triggerGATE
=0;
538 if (thisctr
.count_written
) {
539 if (!thisctr
.OUTpin
) {
542 if (thisctr
.triggerGATE
) {
543 set_count(thisctr
, thisctr
.inlatch
);
544 if (thisctr
.count_binary
==0) {
545 thisctr
.next_change_time
=1;
547 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
549 thisctr
.null_count
=0;
550 if (thisctr
.write_state
==MSByte_multiple
) {
551 BX_ERROR(("Undefined behavior when loading a half loaded count."));
553 thisctr
.first_pass
=1;
556 if (thisctr
.first_pass
) {
557 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
558 if (!thisctr
.count
) {
560 thisctr
.next_change_time
=1;
561 thisctr
.first_pass
=0;
564 thisctr
.next_change_time
=0;
568 thisctr
.next_change_time
=0;
570 thisctr
.triggerGATE
=0;
573 BX_ERROR(("Mode not implemented."));
574 thisctr
.next_change_time
=0;
575 thisctr
.triggerGATE
=0;
581 void pit_82C54::clock_all(Bit32u cycles
)
583 BX_DEBUG(("clock_all: cycles=%d",cycles
));
584 clock_multiple(0,cycles
);
585 clock_multiple(1,cycles
);
586 clock_multiple(2,cycles
);
589 Bit8u
pit_82C54::read(Bit8u address
)
591 if (address
>MAX_ADDRESS
) {
592 BX_ERROR(("Counter address incorrect in data read."));
593 } else if (address
==CONTROL_ADDRESS
) {
594 BX_DEBUG(("PIT Read: Control Word Register."));
595 //Read from control word register;
596 /* This might be okay. If so, 0 seems the most logical
597 * return value from looking at the docs.
599 BX_ERROR(("Read from control word register not defined."));
602 //Read from a counter;
603 BX_DEBUG(("PIT Read: Counter %d.",address
));
604 counter_type
&thisctr
=counter
[address
];
605 if (thisctr
.status_latched
) {
606 //Latched Status Read;
607 if (thisctr
.count_MSB_latched
&&
608 (thisctr
.read_state
==MSByte_multiple
)) {
609 BX_ERROR(("Undefined output when status latched and count half read."));
611 thisctr
.status_latched
=0;
612 return thisctr
.status_latch
;
615 //Latched Count Read;
616 if (thisctr
.count_LSB_latched
) {
617 //Read Least Significant Byte;
618 if (thisctr
.read_state
==LSByte_multiple
) {
619 BX_DEBUG(("Setting read_state to MSB_mult"));
620 thisctr
.read_state
=MSByte_multiple
;
622 thisctr
.count_LSB_latched
=0;
623 return (thisctr
.outlatch
& 0xFF);
624 } else if (thisctr
.count_MSB_latched
) {
625 //Read Most Significant Byte;
626 if (thisctr
.read_state
==MSByte_multiple
) {
627 BX_DEBUG(("Setting read_state to LSB_mult"));
628 thisctr
.read_state
=LSByte_multiple
;
630 thisctr
.count_MSB_latched
=0;
631 return ((thisctr
.outlatch
>>8) & 0xFF);
633 //Unlatched Count Read;
634 if (!(thisctr
.read_state
& 0x1)) {
635 //Read Least Significant Byte;
636 if (thisctr
.read_state
==LSByte_multiple
) {
637 thisctr
.read_state
=MSByte_multiple
;
638 BX_DEBUG(("Setting read_state to MSB_mult"));
640 return (thisctr
.count
& 0xFF);
642 //Read Most Significant Byte;
643 if (thisctr
.read_state
==MSByte_multiple
) {
644 BX_DEBUG(("Setting read_state to LSB_mult"));
645 thisctr
.read_state
=LSByte_multiple
;
647 return ((thisctr
.count
>>8) & 0xFF);
653 //Should only get here on errors;
657 void pit_82C54::write(Bit8u address
, Bit8u data
)
659 if (address
>MAX_ADDRESS
) {
660 BX_ERROR(("Counter address incorrect in data write."));
661 } else if (address
==CONTROL_ADDRESS
) {
662 Bit8u SC
, RW
, M
, BCD
;
664 BX_DEBUG(("Control Word Write."));
665 SC
= (controlword
>>6) & 0x3;
666 RW
= (controlword
>>4) & 0x3;
667 M
= (controlword
>>1) & 0x7;
668 BCD
= controlword
& 0x1;
672 BX_DEBUG(("READ_BACK command."));
673 for(i
=0;i
<=MAX_COUNTER
;i
++) {
675 //If we are using this counter;
676 counter_type
&thisctr
=counter
[i
];
677 if (!((controlword
>>5) & 1)) {
679 latch_counter(thisctr
);
681 if (!((controlword
>>4) & 1)) {
683 if (thisctr
.status_latched
) {
684 //Do nothing because latched status has not been read.;
686 thisctr
.status_latch
=
687 ((thisctr
.OUTpin
& 0x1) << 7) |
688 ((thisctr
.null_count
& 0x1) << 6) |
689 ((thisctr
.rw_mode
& 0x3) << 4) |
690 ((thisctr
.mode
& 0x7) << 1) |
691 (thisctr
.bcd_mode
&0x1);
692 thisctr
.status_latched
=1;
698 counter_type
&thisctr
= counter
[SC
];
700 //Counter Latch command;
701 BX_DEBUG(("Counter Latch command. SC=%d",SC
));
702 latch_counter(thisctr
);
704 //Counter Program Command;
705 BX_DEBUG(("Counter Program command. SC=%d, RW=%d, M=%d, BCD=%d",SC
,RW
,M
,BCD
));
706 thisctr
.null_count
=1;
707 thisctr
.count_LSB_latched
=0;
708 thisctr
.count_MSB_latched
=0;
709 thisctr
.status_latched
=0;
711 thisctr
.count_written
=0;
712 thisctr
.first_pass
=1;
714 thisctr
.bcd_mode
=(BCD
> 0);
718 BX_DEBUG(("Setting read_state to LSB"));
719 thisctr
.read_state
=LSByte
;
720 thisctr
.write_state
=LSByte
;
723 BX_DEBUG(("Setting read_state to MSB"));
724 thisctr
.read_state
=MSByte
;
725 thisctr
.write_state
=MSByte
;
728 BX_DEBUG(("Setting read_state to LSB_mult"));
729 thisctr
.read_state
=LSByte_multiple
;
730 thisctr
.write_state
=LSByte_multiple
;
733 BX_ERROR(("RW field invalid in control word write."));
736 //All modes except mode 0 have initial output of 1.;
742 thisctr
.next_change_time
=0;
746 //Write to counter initial value.
747 counter_type
&thisctr
= counter
[address
];
748 BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address
,data
));
749 switch(thisctr
.write_state
) {
750 case LSByte_multiple
:
751 thisctr
.inlatch
=(thisctr
.inlatch
& (0xFF<<8)) | data
;
752 thisctr
.write_state
=MSByte_multiple
;
755 thisctr
.inlatch
=(thisctr
.inlatch
& (0xFF<<8)) | data
;
756 thisctr
.null_count
=1;
757 thisctr
.count_written
=1;
759 case MSByte_multiple
:
760 thisctr
.write_state
=LSByte_multiple
;
761 case MSByte
: //shared between MSB_multiple and MSByte
762 thisctr
.inlatch
=(thisctr
.inlatch
& 0xFF) | (data
<<8);
763 thisctr
.null_count
=1;
764 thisctr
.count_written
=1;
767 BX_ERROR(("write counter in invalid write state."));
770 switch(thisctr
.mode
) {
772 if (thisctr
.write_state
==MSByte_multiple
) {
775 thisctr
.next_change_time
=1;
778 if (thisctr
.triggerGATE
) { //for initial writes, if already saw trigger.
779 thisctr
.next_change_time
=1;
780 } //Otherwise, no change.
784 thisctr
.next_change_time
=1; //FIXME: this could be loosened.
788 thisctr
.next_change_time
=1; //FIXME: this could be loosened.
791 thisctr
.next_change_time
=1;
794 if (thisctr
.triggerGATE
) { //for initial writes, if already saw trigger.
795 thisctr
.next_change_time
=1;
796 } //Otherwise, no change.
802 void pit_82C54::set_GATE(Bit8u cnum
, bx_bool data
)
804 if (cnum
>MAX_COUNTER
) {
805 BX_ERROR(("Counter number incorrect in 82C54 set_GATE"));
807 counter_type
&thisctr
= counter
[cnum
];
808 if (!((thisctr
.GATE
&&data
) || (!(thisctr
.GATE
||data
)))) {
809 BX_INFO(("Changing GATE %d to: %d",cnum
,data
));
812 thisctr
.triggerGATE
=1;
814 switch(thisctr
.mode
) {
816 if (data
&& thisctr
.count_written
) {
817 if (thisctr
.null_count
) {
818 thisctr
.next_change_time
=1;
820 if ((!thisctr
.OUTpin
) &&
821 (thisctr
.write_state
!=MSByte_multiple
))
823 if (thisctr
.count_binary
==0) {
824 thisctr
.next_change_time
=1;
826 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
829 thisctr
.next_change_time
=0;
833 if (thisctr
.null_count
) {
834 thisctr
.next_change_time
=1;
836 thisctr
.next_change_time
=0;
841 if (data
&& thisctr
.count_written
) { //only triggers cause a change.
842 thisctr
.next_change_time
=1;
848 thisctr
.next_change_time
=0;
850 if (thisctr
.count_written
) {
851 thisctr
.next_change_time
=1;
853 thisctr
.next_change_time
=0;
860 thisctr
.first_pass
=1;
861 thisctr
.next_change_time
=0;
863 if (thisctr
.count_written
) {
864 thisctr
.next_change_time
=1;
866 thisctr
.next_change_time
=0;
871 if (!thisctr
.OUTpin
|| thisctr
.null_count
) {
872 thisctr
.next_change_time
=1;
874 if (data
&& thisctr
.count_written
) {
875 if (thisctr
.first_pass
) {
876 if (thisctr
.count_binary
==0) {
877 thisctr
.next_change_time
=1;
879 thisctr
.next_change_time
=thisctr
.count_binary
& 0xFFFF;
882 thisctr
.next_change_time
=0;
885 thisctr
.next_change_time
=0;
890 if (data
&& thisctr
.count_written
) { //only triggers cause a change.
891 thisctr
.next_change_time
=1;
901 bx_bool
pit_82C54::read_OUT(Bit8u cnum
)
903 if (cnum
>MAX_COUNTER
) {
904 BX_ERROR(("Counter number incorrect in 82C54 read_OUT"));
908 return counter
[cnum
].OUTpin
;
911 bx_bool
pit_82C54::read_GATE(Bit8u cnum
)
913 if (cnum
>MAX_COUNTER
) {
914 BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
918 return counter
[cnum
].GATE
;
921 Bit32u
pit_82C54::get_clock_event_time(Bit8u cnum
)
923 if (cnum
>MAX_COUNTER
) {
924 BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
928 return counter
[cnum
].next_change_time
;
931 Bit32u
pit_82C54::get_next_event_time(void)
934 Bit32u time0
=get_clock_event_time(0);
935 Bit32u time1
=get_clock_event_time(1);
936 Bit32u time2
=get_clock_event_time(2);
939 if (time1
&& (time1
<out
))
941 if (time2
&& (time2
<out
))
946 Bit16u
pit_82C54::get_inlatch(int counternum
)
948 return counter
[counternum
].inlatch
;
951 void pit_82C54::set_OUT_handler(Bit8u counternum
, out_handler_t outh
)
953 counter
[counternum
].out_handler
= outh
;