2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
18 #define MONOSYNC(ch) ((port[ch].wr[4] & 0x3c) == 0x00)
19 #define BISYNC(ch) ((port[ch].wr[4] & 0x3c) == 0x10)
20 //#define SDLC(ch) ((port[ch].wr[4] & 0x3c) == 0x20)
21 //#define EXTSYNC(ch) ((port[ch].wr[4] & 0x3c) == 0x30)
22 #define SYNC_MODE(ch) (MONOSYNC(ch) || BISYNC(ch))
27 #define REGISTER_FIRST_SEND_EVENT(ch) { \
28 if(port[ch].tx_clock != 0) { \
29 if(port[ch].send_id == -1) { \
30 register_event(this, EVENT_SEND + ch, 1000000.0 / port[ch].tx_clock / 2.0, false, &port[ch].send_id); \
33 if(port[ch].tx_bits_x2_remain == 0) { \
34 port[ch].tx_bits_x2_remain = 1; \
39 #define REGISTER_SEND_EVENT(ch) { \
40 if(port[ch].tx_clock != 0) { \
41 if(port[ch].send_id == -1) { \
42 register_event(this, EVENT_SEND + ch, port[ch].tx_interval, false, &port[ch].send_id); \
45 if(port[ch].tx_bits_x2_remain == 0) { \
46 port[ch].tx_bits_x2_remain = port[ch].tx_bits_x2; \
51 #define CANCEL_SEND_EVENT(ch) { \
52 if(port[ch].tx_clock != 0) { \
53 if(port[ch].send_id != -1) { \
54 cancel_event(this, port[ch].send_id); \
55 port[ch].send_id = -1; \
58 port[ch].tx_bits_x2_remain = 0; \
62 #define REGISTER_RECV_EVENT(ch) { \
63 if(port[ch].rx_clock != 0) { \
64 if(port[ch].recv_id == -1) { \
65 register_event(this, EVENT_RECV + ch, port[ch].rx_interval, false, &port[ch].recv_id); \
68 if(port[ch].rx_bits_x2_remain == 0) { \
69 port[ch].rx_bits_x2_remain = port[ch].rx_bits_x2; \
74 #define CANCEL_RECV_EVENT(ch) { \
75 if(port[ch].rx_clock != 0) { \
76 if(port[ch].recv_id != -1) { \
77 cancel_event(this, port[ch].recv_id); \
78 port[ch].recv_id = -1; \
81 port[ch].rx_bits_x2_remain = 0; \
85 void Z80SIO::initialize()
88 __HAS_UPD7201 = osd->check_feature(_T("HAS_UPD7201"));
89 __SIO_DEBUG = osd->check_feature(_T("SIO_DEBUG"));
91 for(int ch = 0; ch < 2; ch++) {
94 port[ch].send = new FIFO(16);
95 port[ch].recv = new FIFO(16);
96 port[ch].rtmp = new FIFO(16);
99 port[ch].send = new FIFO(1);
100 port[ch].recv = new FIFO(4);
101 port[ch].rtmp = new FIFO(8);
102 port[ch].tx_count_hi = 0;
108 port[ch].sync = true;
109 port[ch].sync_bit = 0;
115 for(int ch = 0; ch < 2; ch++) {
116 port[ch].pointer = 0;
117 port[ch].nextrecv_intr = false;
118 port[ch].first_data = false;
119 port[ch].over_flow = false;
120 port[ch].under_run = false;
121 port[ch].abort = false;
123 port[ch].tx_count = 0;
125 port[ch].send->clear();
126 port[ch].recv->clear();
127 port[ch].rtmp->clear();
128 port[ch].shift_reg = -1;
129 port[ch].send_id = -1;
130 port[ch].recv_id = -1;
131 memset(port[ch].wr, 0, sizeof(port[ch].wr));
133 port[ch].err_intr = false;
134 port[ch].recv_intr = 0;
135 port[ch].stat_intr = false;
136 port[ch].send_intr = false;
137 port[ch].req_intr = false;
138 port[ch].in_service = false;
143 void Z80SIO::release()
145 for(int ch = 0; ch < 2; ch++) {
147 port[ch].send->release();
148 delete port[ch].send;
151 port[ch].recv->release();
152 delete port[ch].recv;
155 port[ch].rtmp->release();
156 delete port[ch].rtmp;
168 void Z80SIO::write_io8(uint32_t addr, uint32_t data)
170 int ch = (addr >> 1) & 1;
171 bool update_intr_required = false;
172 bool update_tx_timing_required = false;
173 bool update_rx_timing_required = false;
179 if(port[ch].send_intr) {
180 port[ch].send_intr = false;
183 // register next event
184 if(port[ch].wr[5] & 8) {
185 int tx_data_bits = 5;
186 if((data & 0xe0) == 0x00) {
188 } else if((data & 0xf0) == 0x80) {
190 } else if((data & 0xf8) == 0xc0) {
192 } else if((data & 0xfc) == 0xe0) {
194 } else if((data & 0xfe) == 0xf0) {
197 if(port[ch].tx_data_bits != tx_data_bits) {
198 port[ch].tx_data_bits = tx_data_bits;
199 update_tx_timing(ch);
201 if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && port[ch].send->empty()) {
202 // this is the first data
203 CANCEL_SEND_EVENT(ch);
204 REGISTER_FIRST_SEND_EVENT(ch);
206 REGISTER_SEND_EVENT(ch);
209 CANCEL_SEND_EVENT(ch);
211 //#ifndef HAS_UPD7201
212 if(!__HAS_UPD7201) port[ch].send->clear();
214 port[ch].send->write(data);
216 if(__HAS_UPD7201) port[ch].tx_count++;
223 // if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d WR[%d]=%2x\n"), ch, port[ch].pointer, data);
225 switch(port[ch].pointer) {
227 switch(data & 0x38) {
229 if(port[ch].stat_intr) {
230 port[ch].stat_intr = false;
231 update_intr_required = true;
236 CANCEL_SEND_EVENT(ch);
237 CANCEL_RECV_EVENT(ch);
238 port[ch].nextrecv_intr = false;
239 port[ch].first_data = false;
240 port[ch].over_flow = false;
242 if(__HAS_UPD7201) port[ch].tx_count = 0; // is this correct ???
244 port[ch].send->clear();
245 port[ch].recv->clear();
246 port[ch].rtmp->clear();
247 port[ch].shift_reg = -1;
248 memset(port[ch].wr, 0, sizeof(port[ch].wr));
250 if(port[ch].err_intr) {
251 port[ch].err_intr = false;
252 update_intr_required = true;
254 if(port[ch].recv_intr) {
255 port[ch].recv_intr = 0;
256 update_intr_required = true;
258 if(port[ch].stat_intr) {
259 port[ch].stat_intr = false;
260 update_intr_required = true;
262 if(port[ch].send_intr) {
263 port[ch].send_intr = false;
264 update_intr_required = true;
266 port[ch].req_intr = false;
269 port[ch].nextrecv_intr = true;
272 if(port[ch].send_intr) {
273 port[ch].send_intr = false;
274 update_intr_required = true;
278 port[ch].over_flow = false;
279 if(port[ch].err_intr) {
280 port[ch].err_intr = false;
281 update_intr_required = true;
287 for(int c = 0; c < 2; c++) {
288 if(port[c].in_service) {
289 port[c].in_service = false;
290 update_intr_required = true;
297 switch(data & 0xc0) {
299 // reset receive crc checker
302 // reset transmit crc generator
305 // reset transmit underrun
306 if(port[ch].under_run) {
307 port[ch].under_run = false;
308 if(port[ch].stat_intr) {
309 port[ch].stat_intr = false;
310 update_intr_required = true;
318 if(port[ch].wr[port[ch].pointer] != data) {
319 update_intr_required = true;
323 if((data & 0x11) == 0x11) {
324 // enter hunt/sync phase
327 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (monosync)\n"), ch);
329 port[ch].sync_bit = BIT_SYNC1;
330 } else if(BISYNC(ch)) {
332 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (bisync)\n"), ch);
334 port[ch].sync_bit = BIT_SYNC1 | BIT_SYNC2;
336 port[ch].sync = false;
337 write_signals(&port[ch].outputs_sync, 0xffffffff);
339 if((port[ch].wr[3] & 0xc0) != (data & 0xc0)) {
340 update_rx_timing_required = true;
344 if((port[ch].wr[4] & 0xcd) != (data & 0xcd)) {
345 update_tx_timing_required = update_rx_timing_required = true;
349 if((uint32_t)(port[ch].wr[5] & 2) != (data & 2)) {
351 write_signals(&port[ch].outputs_rts, (data & 2) ? 0 : 0xffffffff);
353 if((uint32_t)(port[ch].wr[5] & 0x80) != (data & 0x80)) {
355 write_signals(&port[ch].outputs_dtr, (data & 0x80) ? 0 : 0xffffffff);
358 if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && !port[ch].send->empty()) {
359 // CANCEL_SEND_EVENT(ch);
360 REGISTER_FIRST_SEND_EVENT(ch);
362 REGISTER_SEND_EVENT(ch);
365 CANCEL_SEND_EVENT(ch);
369 write_signals(&port[ch].outputs_break, 0xffffffff);
371 if((port[ch].wr[5] & 0x60) != (data & 0x60)) {
372 update_tx_timing_required = true;
376 port[ch].wr[port[ch].pointer] = data;
377 if(update_intr_required) {
380 if(update_tx_timing_required) {
381 update_tx_timing(ch);
383 if(update_rx_timing_required) {
384 update_rx_timing(ch);
386 port[ch].pointer = (port[ch].pointer == 0) ? (data & 7) : 0;
391 uint32_t Z80SIO::read_io8(uint32_t addr)
393 int ch = (addr >> 1) & 1;
400 if(port[ch].recv_intr) {
401 // cancel pending interrupt
402 if(--port[ch].recv_intr == 0) {
406 return port[ch].recv->read();
409 if(port[ch].pointer == 0) {
410 if(!port[ch].recv->empty()) {
413 if(ch == 0 && (port[0].req_intr || port[1].req_intr)) {
416 if(!port[ch].send->full()) {
428 if(port[ch].under_run) {
434 } else if(port[ch].pointer == 1) {
436 if(port[ch].send->empty()) {
439 if(port[ch].over_flow) {
442 } else if(port[ch].pointer == 2) {
443 val = port[ch].vector;
445 } else if(port[ch].pointer == 3) {
447 val = port[ch].tx_count & 0xff;
448 port[ch].tx_count_hi = port[ch].tx_count >> 8;
450 } else if(port[ch].pointer == 4) {
452 // val = (port[ch].tx_count >> 8) & 0xff;
453 val = port[ch].tx_count_hi;
457 port[ch].pointer = 0;
463 void Z80SIO::write_signal(int id, uint32_t data, uint32_t mask)
467 bool signal = ((data & mask) != 0);
470 case SIG_Z80SIO_RECV_CH0:
471 case SIG_Z80SIO_RECV_CH1:
473 REGISTER_RECV_EVENT(ch);
474 if(port[ch].rtmp->empty()) {
475 port[ch].first_data = true;
477 port[ch].rtmp->write(data & mask);
479 case SIG_Z80SIO_BREAK_CH0:
480 case SIG_Z80SIO_BREAK_CH1:
482 if((data & mask) && !port[ch].abort) {
483 port[ch].abort = true;
484 if(!port[ch].stat_intr) {
485 port[ch].stat_intr = true;
490 case SIG_Z80SIO_DCD_CH0:
491 case SIG_Z80SIO_DCD_CH1:
492 if(port[ch].dcd != signal) {
493 port[ch].dcd = signal;
494 if(!signal && (port[ch].wr[3] & 0x20)) {
498 if(!port[ch].stat_intr) {
499 port[ch].stat_intr = true;
504 case SIG_Z80SIO_CTS_CH0:
505 case SIG_Z80SIO_CTS_CH1:
506 if(port[ch].cts != signal) {
507 port[ch].cts = signal;
508 if(!signal && (port[ch].wr[3] & 0x20)) {
510 if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && !port[ch].send->empty()) {
511 // CANCEL_SEND_EVENT(ch);
512 REGISTER_FIRST_SEND_EVENT(ch);
514 REGISTER_SEND_EVENT(ch);
518 if(!port[ch].stat_intr) {
519 port[ch].stat_intr = true;
523 case SIG_Z80SIO_SYNC_CH0:
524 case SIG_Z80SIO_SYNC_CH1:
525 if(port[ch].sync != signal) {
526 port[ch].sync = signal;
527 if(!port[ch].stat_intr) {
528 port[ch].stat_intr = true;
533 case SIG_Z80SIO_TX_CLK_CH0:
534 case SIG_Z80SIO_TX_CLK_CH1:
535 if(port[ch].prev_tx_clock_signal != signal) {
536 if(port[ch].tx_bits_x2_remain > 0 && --port[ch].tx_bits_x2_remain == 0) {
537 event_callback(EVENT_SEND + ch, 0);
539 port[ch].prev_tx_clock_signal = signal;
542 case SIG_Z80SIO_RX_CLK_CH0:
543 case SIG_Z80SIO_RX_CLK_CH1:
544 if(port[ch].prev_rx_clock_signal != signal) {
545 if(port[ch].rx_bits_x2_remain > 0 && --port[ch].rx_bits_x2_remain == 0) {
546 event_callback(EVENT_RECV + ch, 0);
548 port[ch].prev_rx_clock_signal = signal;
551 case SIG_Z80SIO_CLEAR_CH0:
552 case SIG_Z80SIO_CLEAR_CH1:
553 // hack: clear recv buffer
555 CANCEL_RECV_EVENT(ch);
556 port[ch].rtmp->clear();
557 port[ch].recv->clear();
558 if(port[ch].recv_intr) {
559 port[ch].recv_intr = 0;
567 void Z80SIO::event_callback(int event_id, int err)
569 int ch = event_id & 1;
571 if(event_id & EVENT_SEND) {
573 port[ch].send_id = -1;
574 port[ch].tx_bits_x2_remain = 0;
576 bool under_run = true;
578 if(port[ch].shift_reg != -1) {
579 // send data in shift register
580 write_signals(&port[ch].outputs_send, port[ch].shift_reg);
581 port[ch].shift_reg = -1;
584 if(!port[ch].send->empty()) {
585 // load data in send buffer to shift register
586 port[ch].shift_reg = port[ch].send->read();
590 // underrun interrupt
591 if(!port[ch].under_run) {
592 port[ch].under_run = true;
593 if(!port[ch].stat_intr) {
594 port[ch].stat_intr = true;
599 if(port[ch].send->empty()) {
600 // transmitter interrupt
601 if(!port[ch].send_intr) {
602 port[ch].send_intr = true;
605 write_signals(&port[ch].outputs_txdone, 0xffffffff);
607 REGISTER_SEND_EVENT(ch);
608 } else if(event_id & EVENT_RECV) {
610 port[ch].recv_id = -1;
611 port[ch].rx_bits_x2_remain = 0;
613 if(!(port[ch].wr[3] & 1)) {
614 REGISTER_RECV_EVENT(ch);
617 bool update_intr_required = false;
619 if(port[ch].recv->full()) {
621 if(!port[ch].over_flow) {
622 port[ch].over_flow = true;
623 if(!port[ch].err_intr) {
624 port[ch].err_intr = true;
625 update_intr_required = true;
630 int data = port[ch].rtmp->read();
632 if(SYNC_MODE(ch) && port[ch].sync_bit != 0) {
633 // receive sync data in monosync/bisync mode ?
634 if(port[ch].sync_bit & BIT_SYNC1) {
635 if(data != port[ch].wr[6]) {
636 goto request_next_data;
639 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv sync1\n"), ch);
641 port[ch].sync_bit &= ~BIT_SYNC1;
642 } else if(port[ch].sync_bit & BIT_SYNC2) {
643 if(data != port[ch].wr[7]) {
644 port[ch].sync_bit |= BIT_SYNC1;
645 goto request_next_data;
648 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv sync2\n"), ch);
650 port[ch].sync_bit &= ~BIT_SYNC2;
652 if(port[ch].sync_bit == 0) {
654 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d leave hunt/sync phase\n"), ch);
656 if(!port[ch].stat_intr) {
657 port[ch].stat_intr = true;
658 update_intr_required = true;
660 port[ch].sync = true;
661 write_signals(&port[ch].outputs_sync, 0);
663 if(port[ch].wr[3] & 2) {
664 // sync char is not loaded into buffer
665 goto request_next_data;
668 // load received data into buffer
670 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv %2x\n"), ch, data);
672 port[ch].recv->write(data);
676 port[ch].abort = false;
677 if(!port[ch].stat_intr) {
678 port[ch].stat_intr = true;
679 update_intr_required = true;
683 // check receive interrupt
685 if((port[ch].wr[1] & 0x18) == 8 && (port[ch].first_data || port[ch].nextrecv_intr)) {
687 } else if(port[ch].wr[1] & 0x10) {
691 if(port[ch].recv_intr++ == 0) {
692 update_intr_required = true;
695 port[ch].first_data = port[ch].nextrecv_intr = false;
698 bool first_data = port[ch].first_data;
699 if(port[ch].rtmp->empty()) {
700 // request data in this message
701 write_signals(&port[ch].outputs_rxdone, 0xffffffff);
703 if(port[ch].rtmp->empty()) {
706 if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d end of block\n"), ch);
708 port[ch].recv_id = -1;
710 REGISTER_RECV_EVENT(ch);
711 port[ch].first_data = first_data;
713 if(update_intr_required) {
719 void Z80SIO::update_tx_timing(int ch)
721 port[ch].tx_bits_x2 = (port[ch].wr[4] & 1) * 2;
722 switch(port[ch].wr[5] & 0x60) {
723 case 0x00: port[ch].tx_bits_x2 += 2 * port[ch].tx_data_bits; break;
724 case 0x20: port[ch].tx_bits_x2 += 2 * 7; break;
725 case 0x40: port[ch].tx_bits_x2 += 2 * 6; break;
726 case 0x60: port[ch].tx_bits_x2 += 2 * 8; break;
728 switch(port[ch].wr[4] & 0x0c) {
729 case 0x00: port[ch].tx_bits_x2 += 0; break; // sync mode
730 case 0x04: port[ch].tx_bits_x2 += 4; break; // 2 * (1 + 1)
731 case 0x08: port[ch].tx_bits_x2 += 5; break; // 2 * (1 + 1.5)
732 case 0x0c: port[ch].tx_bits_x2 += 6; break; // 2 * (1 + 2)
734 switch(port[ch].wr[4] & 0xc0) {
735 case 0x40: port[ch].tx_bits_x2 *= 16; break;
736 case 0x80: port[ch].tx_bits_x2 *= 32; break;
737 case 0xc0: port[ch].tx_bits_x2 *= 64; break;
739 if(port[ch].tx_clock != 0) {
740 port[ch].tx_interval = 1000000.0 / port[ch].tx_clock * (double)port[ch].tx_bits_x2 / 2.0;
744 void Z80SIO::update_rx_timing(int ch)
746 port[ch].rx_bits_x2 = (port[ch].wr[4] & 1) * 2;
747 switch(port[ch].wr[3] & 0xc0) {
748 case 0x00: port[ch].rx_bits_x2 += 2 * 5; break;
749 case 0x40: port[ch].rx_bits_x2 += 2 * 7; break;
750 case 0x80: port[ch].rx_bits_x2 += 2 * 6; break;
751 case 0xc0: port[ch].rx_bits_x2 += 2 * 8; break;
753 switch(port[ch].wr[4] & 0x0c) {
754 case 0x00: port[ch].rx_bits_x2 += 0; break; // sync mode
755 case 0x04: port[ch].rx_bits_x2 += 4; break; // 2 * (1 + 1)
756 case 0x08: port[ch].rx_bits_x2 += 5; break; // 2 * (1 + 1.5)
757 case 0x0c: port[ch].rx_bits_x2 += 6; break; // 2 * (1 + 2)
759 switch(port[ch].wr[4] & 0xc0) {
760 case 0x40: port[ch].rx_bits_x2 *= 16; break;
761 case 0x80: port[ch].rx_bits_x2 *= 32; break;
762 case 0xc0: port[ch].rx_bits_x2 *= 64; break;
764 if(port[ch].rx_clock != 0) {
765 port[ch].rx_interval = 1000000.0 / port[ch].rx_clock * (double)port[ch].rx_bits_x2 / 2.0;
769 void Z80SIO::set_intr_iei(bool val)
777 #define set_intr_oei(val) { \
781 d_child->set_intr_iei(oei); \
786 void Z80SIO::update_intr()
791 if((next = iei) == true) {
792 for(int ch = 0; ch < 2; ch++) {
793 if(port[ch].in_service) {
801 // check interrupt status
802 for(int ch = 0; ch < 2; ch++) {
803 if(port[ch].err_intr) {
804 port[ch].req_intr = true;
805 port[ch].affect = (ch ? 0 : 4) | 3;
806 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
807 port[ch].req_intr = true;
808 port[ch].affect = (ch ? 0 : 4) | 2;
809 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
810 port[ch].req_intr = true;
811 port[ch].affect = (ch ? 0 : 4) | 1;
812 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
813 port[ch].req_intr = true;
814 port[ch].affect = (ch ? 0 : 4) | 0;
816 port[ch].req_intr = false;
821 if(port[1].wr[1] & 4) {
824 uint8_t affect = 7; // no interrupt pending
825 for(int ch = 0; ch < 2; ch++) {
826 if(port[ch].in_service) {
829 if(port[ch].req_intr) {
830 affect = port[ch].affect;
834 uint8_t mode = port[0].wr[2] & 0x38;
835 if(mode == 0 || mode == 8 || mode == 0x20 || mode == 0x28 || mode == 0x38) {
836 port[1].vector = (port[1].wr[2] & 0xe3) | (affect << 2); // 8085
838 port[1].vector = (port[1].wr[2] & 0xf8) | (affect << 0); // 8086
842 uint8_t affect = 3; // no interrupt pending
843 for(int ch = 0; ch < 2; ch++) {
844 if(port[ch].in_service) {
847 if(port[ch].req_intr) {
848 affect = port[ch].affect;
852 port[1].vector = (port[1].wr[2] & 0xf1) | (affect << 1);
856 port[1].vector = port[1].wr[2];
860 if((next = iei) == true) {
862 for(int ch = 0; ch < 2; ch++) {
863 if(port[ch].in_service) {
866 if(port[ch].req_intr) {
873 d_cpu->set_intr_line(next, true, intr_bit);
877 uint32_t Z80SIO::get_intr_ack()
880 for(int ch = 0; ch < 2; ch++) {
881 if(port[ch].in_service) {
882 // invalid interrupt status
885 // priority is error > receive > status > send ???
886 if(port[ch].err_intr) {
887 port[ch].err_intr = false;
888 port[ch].in_service = true;
889 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
890 port[ch].recv_intr = 0;
891 port[ch].in_service = true;
892 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
893 port[ch].stat_intr = false;
894 port[ch].in_service = true;
895 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
896 port[ch].send_intr = false;
897 port[ch].in_service = true;
899 if(port[ch].in_service) {
900 uint8_t vector = port[1].vector;
906 return d_child->get_intr_ack();
911 void Z80SIO::notify_intr_reti()
914 for(int ch = 0; ch < 2; ch++) {
915 if(port[ch].in_service) {
916 port[ch].in_service = false;
922 d_child->notify_intr_reti();
926 #define STATE_VERSION 3
928 bool Z80SIO::process_state(FILEIO* state_fio, bool loading)
930 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
933 if(!state_fio->StateCheckInt32(this_device_id)) {
936 for(int i = 0; i < 2; i++) {
937 state_fio->StateValue(port[i].pointer);
938 state_fio->StateArray(port[i].wr, sizeof(port[i].wr), 1);
939 state_fio->StateValue(port[i].vector);
940 state_fio->StateValue(port[i].affect);
941 state_fio->StateValue(port[i].nextrecv_intr);
942 state_fio->StateValue(port[i].first_data);
943 state_fio->StateValue(port[i].over_flow);
944 state_fio->StateValue(port[i].under_run);
945 state_fio->StateValue(port[i].abort);
946 state_fio->StateValue(port[i].sync);
947 state_fio->StateValue(port[i].sync_bit);
949 state_fio->StateValue(port[i].tx_count);
950 state_fio->StateValue(port[i].tx_count_hi);
952 state_fio->StateValue(port[i].tx_clock);
953 state_fio->StateValue(port[i].tx_interval);
954 state_fio->StateValue(port[i].rx_clock);
955 state_fio->StateValue(port[i].rx_interval);
956 state_fio->StateValue(port[i].tx_data_bits);
957 state_fio->StateValue(port[i].tx_bits_x2);
958 state_fio->StateValue(port[i].tx_bits_x2_remain);
959 state_fio->StateValue(port[i].rx_bits_x2);
960 state_fio->StateValue(port[i].rx_bits_x2_remain);
961 state_fio->StateValue(port[i].prev_tx_clock_signal);
962 state_fio->StateValue(port[i].prev_rx_clock_signal);
963 if(!port[i].send->process_state((void *)state_fio, loading)) {
966 if(!port[i].recv->process_state((void *)state_fio, loading)) {
969 if(!port[i].rtmp->process_state((void *)state_fio, loading)) {
972 state_fio->StateValue(port[i].shift_reg);
973 state_fio->StateValue(port[i].send_id);
974 state_fio->StateValue(port[i].recv_id);
975 state_fio->StateValue(port[i].err_intr);
976 state_fio->StateValue(port[i].recv_intr);
977 state_fio->StateValue(port[i].stat_intr);
978 state_fio->StateValue(port[i].send_intr);
979 state_fio->StateValue(port[i].req_intr);
980 state_fio->StateValue(port[i].in_service);
981 state_fio->StateValue(port[i].dcd);
982 state_fio->StateValue(port[i].cts);
984 state_fio->StateValue(iei);
985 state_fio->StateValue(oei);
986 state_fio->StateValue(intr_bit);