- added instructions how to update the online documentation
[bochs-mirror.git] / iodev / pit82c54.cc
blob0d657684981183b9ce8c6cfbbcf050494f30527a
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: pit82c54.cc,v 1.32 2008/02/15 22:05:43 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 /*
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?
13 * I.E.:
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
20 * unlatched read?
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
24 * clock edge.
25 * 6.)What happens when we trigger mode 1 in the middle of a 2-part
26 * write?
29 #include "iodev.h"
30 #include "pit82c54.h"
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"));
49 } else {
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.;
58 } else {
59 switch(thisctr.read_state) {
60 case MSByte:
61 thisctr.outlatch=thisctr.count & 0xFFFF;
62 thisctr.count_MSB_latched=1;
63 break;
64 case LSByte:
65 thisctr.outlatch=thisctr.count & 0xFFFF;
66 thisctr.count_LSB_latched=1;
67 break;
68 case LSByte_multiple:
69 thisctr.outlatch=thisctr.count & 0xFFFF;
70 thisctr.count_LSB_latched=1;
71 thisctr.count_MSB_latched=1;
72 break;
73 case MSByte_multiple:
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;
85 break;
86 default:
87 BX_ERROR(("Unknown read mode found during latch command."));
88 break;
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) {
114 thisctr.count=
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);
119 } else {
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));
133 } else {
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;
145 } else {
146 thisctr.count=0xFFFF;
147 thisctr.count_binary=0xFFFF;
149 } else {
150 thisctr.count_binary--;
151 set_count_to_binary(thisctr);
155 void pit_82C54::init(void)
157 put("PIT81");
158 settype(PIT81LOG);
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;
164 counter[i].GATE=1;
165 counter[i].OUTpin=1;
166 counter[i].triggerGATE=0;
167 counter[i].mode=4;
168 counter[i].first_pass=0;
169 counter[i].bcd_mode=0;
170 counter[i].count=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;
183 seen_problems=0;
186 pit_82C54::pit_82C54(void)
188 init();
191 void pit_82C54::reset(unsigned type) {}
193 void pit_82C54::register_state(bx_param_c *parent)
195 char name[4];
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)
228 while(cycles>0) {
229 if (cycles<=thisctr.count_binary) {
230 thisctr.count_binary-=cycles;
231 cycles-=cycles;
232 set_count_to_binary(thisctr);
233 } else {
234 cycles-=(thisctr.count_binary+1);
235 thisctr.count_binary-=thisctr.count_binary;
236 set_count_to_binary(thisctr);
237 decrement(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"));
246 } else {
247 counter_type &thisctr = counter[cnum];
248 while(cycles>0) {
249 if (thisctr.next_change_time==0) {
250 if (thisctr.count_written) {
251 switch(thisctr.mode) {
252 case 0:
253 if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
254 decrement_multiple(thisctr, cycles);
256 break;
257 case 1:
258 decrement_multiple(thisctr, cycles);
259 break;
260 case 2:
261 if (!thisctr.first_pass && thisctr.GATE) {
262 decrement_multiple(thisctr, cycles);
264 break;
265 case 3:
266 if (!thisctr.first_pass && thisctr.GATE) {
267 decrement_multiple(thisctr, 2*cycles);
269 break;
270 case 4:
271 if (thisctr.GATE) {
272 decrement_multiple(thisctr, cycles);
274 break;
275 case 5:
276 decrement_multiple(thisctr, cycles);
277 break;
278 default:
279 break;
282 cycles-=cycles;
283 } else {
284 switch(thisctr.mode) {
285 case 0:
286 case 1:
287 case 2:
288 case 4:
289 case 5:
290 if (thisctr.next_change_time > cycles) {
291 decrement_multiple(thisctr,cycles);
292 thisctr.next_change_time-=cycles;
293 cycles-=cycles;
294 } else {
295 decrement_multiple(thisctr,(thisctr.next_change_time-1));
296 cycles-=thisctr.next_change_time;
297 clock(cnum);
299 break;
300 case 3:
301 if (thisctr.next_change_time > cycles) {
302 decrement_multiple(thisctr,cycles*2);
303 thisctr.next_change_time-=cycles;
304 cycles-=cycles;
305 } else {
306 decrement_multiple(thisctr,(thisctr.next_change_time-1)*2);
307 cycles-=thisctr.next_change_time;
308 clock(cnum);
310 break;
311 default:
312 cycles-=cycles;
313 break;
317 #if 0
318 print_counter(thisctr);
319 #endif
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"));
328 } else {
329 counter_type &thisctr = counter[cnum];
330 switch(thisctr.mode) {
331 case 0:
332 if (thisctr.count_written) {
333 if (thisctr.null_count) {
334 set_count(thisctr, thisctr.inlatch);
335 if (thisctr.GATE) {
336 if (thisctr.count_binary==0) {
337 thisctr.next_change_time=1;
338 } else {
339 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
341 } else {
342 thisctr.next_change_time=0;
344 thisctr.null_count=0;
345 } else {
346 if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
347 decrement(thisctr);
348 if (!thisctr.OUTpin) {
349 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
350 if (!thisctr.count) {
351 set_OUT(thisctr,1);
353 } else {
354 thisctr.next_change_time=0;
356 } else {
357 thisctr.next_change_time=0; //if the clock isn't moving.
360 } else {
361 thisctr.next_change_time=0; //default to 0.
363 thisctr.triggerGATE=0;
364 break;
365 case 1:
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;
371 } else {
372 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
374 thisctr.null_count=0;
375 set_OUT(thisctr,0);
376 if (thisctr.write_state==MSByte_multiple) {
377 BX_ERROR(("Undefined behavior when loading a half loaded count."));
379 } else {
380 decrement(thisctr);
381 if (!thisctr.OUTpin) {
382 if (thisctr.count_binary==0) {
383 thisctr.next_change_time=1;
384 } else {
385 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
387 if (thisctr.count==0) {
388 set_OUT(thisctr,1);
390 } else {
391 thisctr.next_change_time=0;
394 } else {
395 thisctr.next_change_time=0; //default to 0.
397 thisctr.triggerGATE=0;
398 break;
399 case 2:
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) {
409 set_OUT(thisctr,1);
411 if (thisctr.write_state==MSByte_multiple) {
412 BX_ERROR(("Undefined behavior when loading a half loaded count."));
414 thisctr.first_pass=0;
415 } else {
416 if (thisctr.GATE) {
417 decrement(thisctr);
418 thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF;
419 if (thisctr.count==1) {
420 thisctr.next_change_time=1;
421 set_OUT(thisctr,0);
422 thisctr.first_pass=1;
424 } else {
425 thisctr.next_change_time=0;
428 } else {
429 thisctr.next_change_time=0;
431 thisctr.triggerGATE=0;
432 break;
433 case 3:
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;
442 } else {
443 thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
445 } else {
446 if ((thisctr.count_binary/2)==0) {
447 thisctr.next_change_time=1;
448 } else {
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) {
457 set_OUT(thisctr,1);
458 } else if (thisctr.OUTpin && !thisctr.first_pass) {
459 set_OUT(thisctr,0);
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;
466 } else {
467 if (thisctr.GATE) {
468 decrement(thisctr);
469 decrement(thisctr);
470 if (!thisctr.OUTpin || !thisctr.state_bit_1) {
471 thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
472 } else {
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;
485 } else {
486 thisctr.next_change_time=0;
489 } else {
490 thisctr.next_change_time=0;
492 thisctr.triggerGATE=0;
493 break;
494 case 4:
495 if (thisctr.count_written) {
496 if (!thisctr.OUTpin) {
497 set_OUT(thisctr,1);
499 if (thisctr.null_count) {
500 set_count(thisctr, thisctr.inlatch);
501 if (thisctr.GATE) {
502 if (thisctr.count_binary==0) {
503 thisctr.next_change_time=1;
504 } else {
505 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
507 } else {
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;
515 } else {
516 if (thisctr.GATE) {
517 decrement(thisctr);
518 if (thisctr.first_pass) {
519 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
520 if (!thisctr.count) {
521 set_OUT(thisctr,0);
522 thisctr.next_change_time=1;
523 thisctr.first_pass=0;
525 } else {
526 thisctr.next_change_time=0;
528 } else {
529 thisctr.next_change_time=0;
532 } else {
533 thisctr.next_change_time=0;
535 thisctr.triggerGATE=0;
536 break;
537 case 5:
538 if (thisctr.count_written) {
539 if (!thisctr.OUTpin) {
540 set_OUT(thisctr,1);
542 if (thisctr.triggerGATE) {
543 set_count(thisctr, thisctr.inlatch);
544 if (thisctr.count_binary==0) {
545 thisctr.next_change_time=1;
546 } else {
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;
554 } else {
555 decrement(thisctr);
556 if (thisctr.first_pass) {
557 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
558 if (!thisctr.count) {
559 set_OUT(thisctr,0);
560 thisctr.next_change_time=1;
561 thisctr.first_pass=0;
563 } else {
564 thisctr.next_change_time=0;
567 } else {
568 thisctr.next_change_time=0;
570 thisctr.triggerGATE=0;
571 break;
572 default:
573 BX_ERROR(("Mode not implemented."));
574 thisctr.next_change_time=0;
575 thisctr.triggerGATE=0;
576 break;
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."));
600 return 0;
601 } else {
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."));
610 } else {
611 thisctr.status_latched=0;
612 return thisctr.status_latch;
614 } else {
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);
632 } else {
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);
641 } else {
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;
654 return 0;
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;
663 controlword=data;
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;
669 if (SC == 3) {
670 //READ_BACK command;
671 int i;
672 BX_DEBUG(("READ_BACK command."));
673 for(i=0;i<=MAX_COUNTER;i++) {
674 if ((M>>i) & 0x1) {
675 //If we are using this counter;
676 counter_type &thisctr=counter[i];
677 if (!((controlword>>5) & 1)) {
678 //Latch Count;
679 latch_counter(thisctr);
681 if (!((controlword>>4) & 1)) {
682 //Latch Status;
683 if (thisctr.status_latched) {
684 //Do nothing because latched status has not been read.;
685 } else {
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;
697 } else {
698 counter_type &thisctr = counter[SC];
699 if (!RW) {
700 //Counter Latch command;
701 BX_DEBUG(("Counter Latch command. SC=%d",SC));
702 latch_counter(thisctr);
703 } else {
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;
710 thisctr.inlatch=0;
711 thisctr.count_written=0;
712 thisctr.first_pass=1;
713 thisctr.rw_mode=RW;
714 thisctr.bcd_mode=(BCD > 0);
715 thisctr.mode=M;
716 switch(RW) {
717 case 0x1:
718 BX_DEBUG(("Setting read_state to LSB"));
719 thisctr.read_state=LSByte;
720 thisctr.write_state=LSByte;
721 break;
722 case 0x2:
723 BX_DEBUG(("Setting read_state to MSB"));
724 thisctr.read_state=MSByte;
725 thisctr.write_state=MSByte;
726 break;
727 case 0x3:
728 BX_DEBUG(("Setting read_state to LSB_mult"));
729 thisctr.read_state=LSByte_multiple;
730 thisctr.write_state=LSByte_multiple;
731 break;
732 default:
733 BX_ERROR(("RW field invalid in control word write."));
734 break;
736 //All modes except mode 0 have initial output of 1.;
737 if (M) {
738 set_OUT(thisctr, 1);
739 } else {
740 set_OUT(thisctr, 0);
742 thisctr.next_change_time=0;
745 } else {
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;
753 break;
754 case LSByte:
755 thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data;
756 thisctr.null_count=1;
757 thisctr.count_written=1;
758 break;
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;
765 break;
766 default:
767 BX_ERROR(("write counter in invalid write state."));
768 break;
770 switch(thisctr.mode) {
771 case 0:
772 if (thisctr.write_state==MSByte_multiple) {
773 set_OUT(thisctr,0);
775 thisctr.next_change_time=1;
776 break;
777 case 1:
778 if (thisctr.triggerGATE) { //for initial writes, if already saw trigger.
779 thisctr.next_change_time=1;
780 } //Otherwise, no change.
781 break;
782 case 6:
783 case 2:
784 thisctr.next_change_time=1; //FIXME: this could be loosened.
785 break;
786 case 7:
787 case 3:
788 thisctr.next_change_time=1; //FIXME: this could be loosened.
789 break;
790 case 4:
791 thisctr.next_change_time=1;
792 break;
793 case 5:
794 if (thisctr.triggerGATE) { //for initial writes, if already saw trigger.
795 thisctr.next_change_time=1;
796 } //Otherwise, no change.
797 break;
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"));
806 } else {
807 counter_type &thisctr = counter[cnum];
808 if (!((thisctr.GATE&&data) || (!(thisctr.GATE||data)))) {
809 BX_INFO(("Changing GATE %d to: %d",cnum,data));
810 thisctr.GATE=data;
811 if (thisctr.GATE) {
812 thisctr.triggerGATE=1;
814 switch(thisctr.mode) {
815 case 0:
816 if (data && thisctr.count_written) {
817 if (thisctr.null_count) {
818 thisctr.next_change_time=1;
819 } else {
820 if ((!thisctr.OUTpin) &&
821 (thisctr.write_state!=MSByte_multiple))
823 if (thisctr.count_binary==0) {
824 thisctr.next_change_time=1;
825 } else {
826 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
828 } else {
829 thisctr.next_change_time=0;
832 } else {
833 if (thisctr.null_count) {
834 thisctr.next_change_time=1;
835 } else {
836 thisctr.next_change_time=0;
839 break;
840 case 1:
841 if (data && thisctr.count_written) { //only triggers cause a change.
842 thisctr.next_change_time=1;
844 break;
845 case 2:
846 if (!data) {
847 set_OUT(thisctr,1);
848 thisctr.next_change_time=0;
849 } else {
850 if (thisctr.count_written) {
851 thisctr.next_change_time=1;
852 } else {
853 thisctr.next_change_time=0;
856 break;
857 case 3:
858 if (!data) {
859 set_OUT(thisctr,1);
860 thisctr.first_pass=1;
861 thisctr.next_change_time=0;
862 } else {
863 if (thisctr.count_written) {
864 thisctr.next_change_time=1;
865 } else {
866 thisctr.next_change_time=0;
869 break;
870 case 4:
871 if (!thisctr.OUTpin || thisctr.null_count) {
872 thisctr.next_change_time=1;
873 } else {
874 if (data && thisctr.count_written) {
875 if (thisctr.first_pass) {
876 if (thisctr.count_binary==0) {
877 thisctr.next_change_time=1;
878 } else {
879 thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
881 } else {
882 thisctr.next_change_time=0;
884 } else {
885 thisctr.next_change_time=0;
888 break;
889 case 5:
890 if (data && thisctr.count_written) { //only triggers cause a change.
891 thisctr.next_change_time=1;
893 break;
894 default:
895 break;
901 bx_bool pit_82C54::read_OUT(Bit8u cnum)
903 if (cnum>MAX_COUNTER) {
904 BX_ERROR(("Counter number incorrect in 82C54 read_OUT"));
905 return 0;
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"));
915 return 0;
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"));
925 return 0;
928 return counter[cnum].next_change_time;
931 Bit32u pit_82C54::get_next_event_time(void)
933 Bit32u out;
934 Bit32u time0=get_clock_event_time(0);
935 Bit32u time1=get_clock_event_time(1);
936 Bit32u time2=get_clock_event_time(2);
938 out=time0;
939 if (time1 && (time1<out))
940 out=time1;
941 if (time2 && (time2<out))
942 out=time2;
943 return 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;