OSDN Git Service

[General][CMAKE] Integrate all devices to upstream 2015-12-17.
[csp-qt/common_source_project-fm7.git] / source / src / vm / z80sio.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.12.31 -
6
7         [ Z80SIO ]
8 */
9
10 #include "z80sio.h"
11 #include "../fifo.h"
12
13 #define EVENT_SEND      2
14 #define EVENT_RECV      4
15
16 //#define SIO_DEBUG
17
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))
23
24 #define BIT_SYNC1       1
25 #define BIT_SYNC2       2
26
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); \
31                 } \
32         } else { \
33                 if(port[ch].tx_bits_x2_remain == 0) { \
34                         port[ch].tx_bits_x2_remain = 1; \
35                 } \
36         } \
37 }
38
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); \
43                 } \
44         } else { \
45                 if(port[ch].tx_bits_x2_remain == 0) { \
46                         port[ch].tx_bits_x2_remain = port[ch].tx_bits_x2; \
47                 } \
48         } \
49 }
50
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; \
56                 } \
57         } else { \
58                 port[ch].tx_bits_x2_remain = 0; \
59         } \
60 }
61
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); \
66                 } \
67         } else { \
68                 if(port[ch].rx_bits_x2_remain == 0) { \
69                         port[ch].rx_bits_x2_remain = port[ch].rx_bits_x2; \
70                 } \
71         } \
72 }
73
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; \
79                 } \
80         } else { \
81                 port[ch].rx_bits_x2_remain = 0; \
82         } \
83 }
84
85 void Z80SIO::initialize()
86 {
87         for(int ch = 0; ch < 2; ch++) {
88 #ifdef HAS_UPD7201
89                 port[ch].send = new FIFO(16);
90                 port[ch].recv = new FIFO(16);
91                 port[ch].rtmp = new FIFO(16);
92 #else
93                 port[ch].send = new FIFO(1);
94                 port[ch].recv = new FIFO(4);
95                 port[ch].rtmp = new FIFO(8);
96 #endif
97                 // input signals
98                 port[ch].dcd = true;
99                 port[ch].cts = true;
100                 port[ch].sync = true;
101                 port[ch].sync_bit = 0;
102         }
103 }
104
105 void Z80SIO::reset()
106 {
107         for(int ch = 0; ch < 2; ch++) {
108                 port[ch].pointer = 0;
109                 port[ch].nextrecv_intr = false;
110                 port[ch].first_data = false;
111                 port[ch].over_flow = false;
112                 port[ch].under_run = false;
113                 port[ch].abort = false;
114 #ifdef HAS_UPD7201
115                 port[ch].tx_count = 0;
116 #endif
117                 port[ch].send->clear();
118                 port[ch].recv->clear();
119                 port[ch].rtmp->clear();
120                 port[ch].shift_reg = -1;
121                 port[ch].send_id = -1;
122                 port[ch].recv_id = -1;
123                 memset(port[ch].wr, 0, sizeof(port[ch].wr));
124                 // interrupt
125                 port[ch].err_intr = false;
126                 port[ch].recv_intr = 0;
127                 port[ch].stat_intr = false;
128                 port[ch].send_intr = false;
129                 port[ch].req_intr = false;
130                 port[ch].in_service = false;
131         }
132         iei = oei = true;
133 }
134
135 void Z80SIO::release()
136 {
137         for(int ch = 0; ch < 2; ch++) {
138                 if(port[ch].send) {
139                         port[ch].send->release();
140                         delete port[ch].send;
141                 }
142                 if(port[ch].recv) {
143                         port[ch].recv->release();
144                         delete port[ch].recv;
145                 }
146                 if(port[ch].rtmp) {
147                         port[ch].rtmp->release();
148                         delete port[ch].rtmp;
149                 }
150         }
151 }
152
153 /*
154         0       ch.a data
155         1       ch.a control
156         2       ch.b data
157         3       ch.b control
158 */
159
160 void Z80SIO::write_io8(uint32 addr, uint32 data)
161 {
162         int ch = (addr >> 1) & 1;
163         bool update_intr_required = false;
164         bool update_tx_timing_required = false;
165         bool update_rx_timing_required = false;
166         
167         switch(addr & 3) {
168         case 0:
169         case 2:
170                 // send data
171                 if(port[ch].send_intr) {
172                         port[ch].send_intr = false;
173                         update_intr();
174                 }
175                 // register next event
176                 if(port[ch].wr[5] & 8) {
177                         int tx_data_bits = 5;
178                         if((data & 0xe0) == 0x00) {
179                                 tx_data_bits = 5;
180                         } else if((data & 0xf0) == 0x80) {
181                                 tx_data_bits = 4;
182                         } else if((data & 0xf8) == 0xc0) {
183                                 tx_data_bits = 3;
184                         } else if((data & 0xfc) == 0xe0) {
185                                 tx_data_bits = 2;
186                         } else if((data & 0xfe) == 0xf0) {
187                                 tx_data_bits = 1;
188                         }
189                         if(port[ch].tx_data_bits != tx_data_bits) {
190                                 port[ch].tx_data_bits = tx_data_bits;
191                                 update_tx_timing(ch);
192                         }
193                         if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && port[ch].send->empty()) {
194                                 // this is the first data
195                                 CANCEL_SEND_EVENT(ch);
196                                 REGISTER_FIRST_SEND_EVENT(ch);
197                         } else {
198                                 REGISTER_SEND_EVENT(ch);
199                         }
200                 } else {
201                         CANCEL_SEND_EVENT(ch);
202                 }
203 #ifndef HAS_UPD7201
204                 port[ch].send->clear();
205 #endif
206                 port[ch].send->write(data);
207 #ifdef HAS_UPD7201
208                 port[ch].tx_count++;
209 #endif
210                 break;
211         case 1:
212         case 3:
213                 // control
214 #ifdef SIO_DEBUG
215 //              emu->out_debug_log(_T("Z80SIO: ch=%d WR[%d]=%2x\n"), ch, port[ch].pointer, data);
216 #endif
217                 switch(port[ch].pointer) {
218                 case 0:
219                         switch(data & 0x38) {
220                         case 0x10:
221                                 if(port[ch].stat_intr) {
222                                         port[ch].stat_intr = false;
223                                         update_intr_required = true;
224                                 }
225                                 break;
226                         case 0x18:
227                                 // channel reset
228                                 CANCEL_SEND_EVENT(ch);
229                                 CANCEL_RECV_EVENT(ch);
230                                 port[ch].nextrecv_intr = false;
231                                 port[ch].first_data = false;
232                                 port[ch].over_flow = false;
233 #ifdef HAS_UPD7201
234                                 port[ch].tx_count = 0;  // is this correct ???
235 #endif
236                                 port[ch].send->clear();
237                                 port[ch].recv->clear();
238                                 port[ch].rtmp->clear();
239                                 port[ch].shift_reg = -1;
240                                 memset(port[ch].wr, 0, sizeof(port[ch].wr));
241                                 // interrupt
242                                 if(port[ch].err_intr) {
243                                         port[ch].err_intr = false;
244                                         update_intr_required = true;
245                                 }
246                                 if(port[ch].recv_intr) {
247                                         port[ch].recv_intr = 0;
248                                         update_intr_required = true;
249                                 }
250                                 if(port[ch].stat_intr) {
251                                         port[ch].stat_intr = false;
252                                         update_intr_required = true;
253                                 }
254                                 if(port[ch].send_intr) {
255                                         port[ch].send_intr = false;
256                                         update_intr_required = true;
257                                 }
258                                 port[ch].req_intr = false;
259                                 break;
260                         case 0x20:
261                                 port[ch].nextrecv_intr = true;
262                                 break;
263                         case 0x28:
264                                 if(port[ch].send_intr) {
265                                         port[ch].send_intr = false;
266                                         update_intr_required = true;
267                                 }
268                                 break;
269                         case 0x30:
270                                 port[ch].over_flow = false;
271                                 if(port[ch].err_intr) {
272                                         port[ch].err_intr = false;
273                                         update_intr_required = true;
274                                 }
275                                 break;
276                         case 0x38:
277                                 // end of interrupt
278                                 if(ch == 0) {
279                                         for(int c = 0; c < 2; c++) {
280                                                 if(port[c].in_service) {
281                                                         port[c].in_service = false;
282                                                         update_intr_required = true;
283                                                         break;
284                                                 }
285                                         }
286                                 }
287                                 break;
288                         }
289                         switch(data & 0xc0) {
290                         case 0x40:
291                                 // reset receive crc checker
292                                 break;
293                         case 0x80:
294                                 // reset transmit crc generator
295                                 break;
296                         case 0xc0:
297                                 // reset transmit underrun
298                                 if(port[ch].under_run) {
299                                         port[ch].under_run = false;
300                                         if(port[ch].stat_intr) {
301                                                 port[ch].stat_intr = false;
302                                                 update_intr_required = true;
303                                         }
304                                 }
305                                 break;
306                         }
307                         break;
308                 case 1:
309                 case 2:
310                         if(port[ch].wr[port[ch].pointer] != data) {
311                                 update_intr_required = true;
312                         }
313                         break;
314                 case 3:
315                         if((data & 0x11) == 0x11) {
316                                 // enter hunt/sync phase
317                                 if(MONOSYNC(ch)) {
318 #ifdef SIO_DEBUG
319                                         emu->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (monosync)\n"), ch);
320 #endif
321                                         port[ch].sync_bit = BIT_SYNC1;
322                                 } else if(BISYNC(ch)) {
323 #ifdef SIO_DEBUG
324                                         emu->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (bisync)\n"), ch);
325 #endif
326                                         port[ch].sync_bit = BIT_SYNC1 | BIT_SYNC2;
327                                 }
328                                 port[ch].sync = false;
329                                 write_signals(&port[ch].outputs_sync, 0xffffffff);
330                         }
331                         if((port[ch].wr[3] & 0xc0) != (data & 0xc0)) {
332                                 update_rx_timing_required = true;
333                         }
334                         break;
335                 case 4:
336                         if((port[ch].wr[4] & 0xcd) != (data & 0xcd)) {
337                                 update_tx_timing_required = update_rx_timing_required = true;
338                         }
339                         break;
340                 case 5:
341                         if((uint32)(port[ch].wr[5] & 2) != (data & 2)) {
342                                 // rts
343                                 write_signals(&port[ch].outputs_rts, (data & 2) ? 0 : 0xffffffff);
344                         }
345                         if((uint32)(port[ch].wr[5] & 0x80) != (data & 0x80)) {
346                                 // dtr
347                                 write_signals(&port[ch].outputs_dtr, (data & 0x80) ? 0 : 0xffffffff);
348                         }
349                         if(data & 8) {
350                                 if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && !port[ch].send->empty()) {
351 //                                      CANCEL_SEND_EVENT(ch);
352                                         REGISTER_FIRST_SEND_EVENT(ch);
353                                 } else {
354                                         REGISTER_SEND_EVENT(ch);
355                                 }
356                         } else {
357                                 CANCEL_SEND_EVENT(ch);
358                         }
359                         if(data & 0x10) {
360                                 // send break
361                                 write_signals(&port[ch].outputs_break, 0xffffffff);
362                         }
363                         if((port[ch].wr[5] & 0x60) != (data & 0x60)) {
364                                 update_tx_timing_required = true;
365                         }
366                         break;
367                 }
368                 port[ch].wr[port[ch].pointer] = data;
369                 if(update_intr_required) {
370                         update_intr();
371                 }
372                 if(update_tx_timing_required) {
373                         update_tx_timing(ch);
374                 }
375                 if(update_rx_timing_required) {
376                         update_rx_timing(ch);
377                 }
378                 port[ch].pointer = (port[ch].pointer == 0) ? (data & 7) : 0;
379                 break;
380         }
381 }
382
383 uint32 Z80SIO::read_io8(uint32 addr)
384 {
385         int ch = (addr >> 1) & 1;
386         uint32 val = 0;
387         
388         switch(addr & 3) {
389         case 0:
390         case 2:
391                 // recv data;
392                 if(port[ch].recv_intr) {
393                         // cancel pending interrupt
394                         if(--port[ch].recv_intr == 0) {
395                                 update_intr();
396                         }
397                 }
398                 return port[ch].recv->read();
399         case 1:
400         case 3:
401                 if(port[ch].pointer == 0) {
402                         if(!port[ch].recv->empty()) {
403                                 val |= 1;
404                         }
405                         if(ch == 0 && (port[0].req_intr || port[1].req_intr)) {
406                                 val |= 2;
407                         }
408                         if(!port[ch].send->full()) {
409                                 val |= 4;       // ???
410                         }
411                         if(!port[ch].dcd) {
412                                 val |= 8;
413                         }
414                         if(!port[ch].sync) {
415                                 val |= 0x10;
416                         }
417                         if(!port[ch].cts) {
418                                 val |= 0x20;
419                         }
420                         if(port[ch].under_run) {
421                                 val |= 0x40;
422                         }
423                         if(port[ch].abort) {
424                                 val |= 0x80;
425                         }
426                 } else if(port[ch].pointer == 1) {
427                         val = 0x8e;     // TODO
428                         if(port[ch].send->empty()) {
429                                 val |= 1;
430                         }
431                         if(port[ch].over_flow) {
432                                 val |= 0x20;
433                         }
434                 } else if(port[ch].pointer == 2) {
435                         val = port[ch].vector;
436 #ifdef HAS_UPD7201
437                 } else if(port[ch].pointer == 3) {
438                         val = port[ch].tx_count & 0xff;
439                         port[ch].tx_count_hi = port[ch].tx_count >> 8;
440                 } else if(port[ch].pointer == 4) {
441 //                      val = (port[ch].tx_count >> 8) & 0xff;
442                         val = port[ch].tx_count_hi;
443 #endif
444                 }
445                 port[ch].pointer = 0;
446                 return val;
447         }
448         return 0xff;
449 }
450
451 void Z80SIO::write_signal(int id, uint32 data, uint32 mask)
452 {
453         // recv data
454         int ch = id & 1;
455         bool signal = ((data & mask) != 0);
456         
457         switch(id) {
458         case SIG_Z80SIO_RECV_CH0:
459         case SIG_Z80SIO_RECV_CH1:
460                 // recv data
461                 REGISTER_RECV_EVENT(ch);
462                 if(port[ch].rtmp->empty()) {
463                         port[ch].first_data = true;
464                 }
465                 port[ch].rtmp->write(data & mask);
466                 break;
467         case SIG_Z80SIO_BREAK_CH0:
468         case SIG_Z80SIO_BREAK_CH1:
469                 // recv break
470                 if((data & mask) && !port[ch].abort) {
471                         port[ch].abort = true;
472                         if(!port[ch].stat_intr) {
473                                 port[ch].stat_intr = true;
474                                 update_intr();
475                         }
476                 }
477                 break;
478         case SIG_Z80SIO_DCD_CH0:
479         case SIG_Z80SIO_DCD_CH1:
480                 if(port[ch].dcd != signal) {
481                         port[ch].dcd = signal;
482                         if(!signal && (port[ch].wr[3] & 0x20)) {
483                                 // auto enables
484                                 port[ch].wr[3] |= 1;
485                         }
486                         if(!port[ch].stat_intr) {
487                                 port[ch].stat_intr = true;
488                                 update_intr();
489                         }
490                 }
491                 break;
492         case SIG_Z80SIO_CTS_CH0:
493         case SIG_Z80SIO_CTS_CH1:
494                 if(port[ch].cts != signal) {
495                         port[ch].cts = signal;
496                         if(!signal && (port[ch].wr[3] & 0x20)) {
497                                 // auto enables
498                                 if((port[ch].wr[4] & 0x0c) != 0 && port[ch].shift_reg == -1 && !port[ch].send->empty()) {
499 //                                      CANCEL_SEND_EVENT(ch);
500                                         REGISTER_FIRST_SEND_EVENT(ch);
501                                 } else {
502                                         REGISTER_SEND_EVENT(ch);
503                                 }
504                                 port[ch].wr[5] |= 8;
505                         }
506                         if(!port[ch].stat_intr) {
507                                 port[ch].stat_intr = true;
508                                 update_intr();
509                         }
510                 }
511         case SIG_Z80SIO_SYNC_CH0:
512         case SIG_Z80SIO_SYNC_CH1:
513                 if(port[ch].sync != signal) {
514                         port[ch].sync = signal;
515                         if(!port[ch].stat_intr) {
516                                 port[ch].stat_intr = true;
517                                 update_intr();
518                         }
519                 }
520                 break;
521         case SIG_Z80SIO_TX_CLK_CH0:
522         case SIG_Z80SIO_TX_CLK_CH1:
523                 if(port[ch].prev_tx_clock_signal != signal) {
524                         if(port[ch].tx_bits_x2_remain > 0 && --port[ch].tx_bits_x2_remain == 0) {
525                                 event_callback(EVENT_SEND + ch, 0);
526                         }
527                         port[ch].prev_tx_clock_signal = signal;
528                 }
529                 break;
530         case SIG_Z80SIO_RX_CLK_CH0:
531         case SIG_Z80SIO_RX_CLK_CH1:
532                 if(port[ch].prev_rx_clock_signal != signal) {
533                         if(port[ch].rx_bits_x2_remain > 0 && --port[ch].rx_bits_x2_remain == 0) {
534                                 event_callback(EVENT_RECV + ch, 0);
535                         }
536                         port[ch].prev_rx_clock_signal = signal;
537                 }
538                 break;
539         case SIG_Z80SIO_CLEAR_CH0:
540         case SIG_Z80SIO_CLEAR_CH1:
541                 // hack: clear recv buffer
542                 if(data & mask) {
543                         CANCEL_RECV_EVENT(ch);
544                         port[ch].rtmp->clear();
545                         port[ch].recv->clear();
546                         if(port[ch].recv_intr) {
547                                 port[ch].recv_intr = 0;
548                                 update_intr();
549                         }
550                 }
551                 break;
552         }
553 }
554
555 void Z80SIO::event_callback(int event_id, int err)
556 {
557         int ch = event_id & 1;
558         
559         if(event_id & EVENT_SEND) {
560                 // send
561                 port[ch].send_id = -1;
562                 port[ch].tx_bits_x2_remain = 0;
563                 
564                 bool under_run = true;
565                 
566                 if(port[ch].shift_reg != -1) {
567                         // send data in shift register
568                         write_signals(&port[ch].outputs_send, port[ch].shift_reg);
569                         port[ch].shift_reg = -1;
570                         under_run = false;
571                 }
572                 if(!port[ch].send->empty()) {
573                         // load data in send buffer to shift register
574                         port[ch].shift_reg = port[ch].send->read();
575                         under_run = false;
576                 }
577                 if(under_run) {
578                         // underrun interrupt
579                         if(!port[ch].under_run) {
580                                 port[ch].under_run = true;
581                                 if(!port[ch].stat_intr) {
582                                         port[ch].stat_intr = true;
583                                         update_intr();
584                                 }
585                         }
586                 }
587                 if(port[ch].send->empty()) {
588                         // transmitter interrupt
589                         if(!port[ch].send_intr) {
590                                 port[ch].send_intr = true;
591                                 update_intr();
592                         }
593                         write_signals(&port[ch].outputs_txdone, 0xffffffff);
594                 }
595                 REGISTER_SEND_EVENT(ch);
596         } else if(event_id & EVENT_RECV) {
597                 // recv
598                 port[ch].recv_id = -1;
599                 port[ch].rx_bits_x2_remain = 0;
600                 
601                 if(!(port[ch].wr[3] & 1)) {
602                         REGISTER_RECV_EVENT(ch);
603                         return;
604                 }
605                 bool update_intr_required = false;
606                 
607                 if(port[ch].recv->full()) {
608                         // overflow
609                         if(!port[ch].over_flow) {
610                                 port[ch].over_flow = true;
611                                 if(!port[ch].err_intr) {
612                                         port[ch].err_intr = true;
613                                         update_intr_required = true;
614                                 }
615                         }
616                 } else {
617                         // no error
618                         int data = port[ch].rtmp->read();
619                         
620                         if(SYNC_MODE(ch) && port[ch].sync_bit != 0) {
621                                 // receive sync data in monosync/bisync mode ?
622                                 if(port[ch].sync_bit & BIT_SYNC1) {
623                                         if(data != port[ch].wr[6]) {
624                                                 goto request_next_data;
625                                         }
626 #ifdef SIO_DEBUG
627                                         emu->out_debug_log(_T("Z80SIO: ch=%d recv sync1\n"), ch);
628 #endif
629                                         port[ch].sync_bit &= ~BIT_SYNC1;
630                                 } else if(port[ch].sync_bit & BIT_SYNC2) {
631                                         if(data != port[ch].wr[7]) {
632                                                 port[ch].sync_bit |= BIT_SYNC1;
633                                                 goto request_next_data;
634                                         }
635 #ifdef SIO_DEBUG
636                                         emu->out_debug_log(_T("Z80SIO: ch=%d recv sync2\n"), ch);
637 #endif
638                                         port[ch].sync_bit &= ~BIT_SYNC2;
639                                 }
640                                 if(port[ch].sync_bit == 0) {
641 #ifdef SIO_DEBUG
642                                         emu->out_debug_log(_T("Z80SIO: ch=%d leave hunt/sync phase\n"), ch);
643 #endif
644                                         if(!port[ch].stat_intr) {
645                                                 port[ch].stat_intr = true;
646                                                 update_intr_required = true;
647                                         }
648                                         port[ch].sync = true;
649                                         write_signals(&port[ch].outputs_sync, 0);
650                                 }
651                                 if(port[ch].wr[3] & 2) {
652                                         // sync char is not loaded into buffer
653                                         goto request_next_data;
654                                 }
655                         }
656                         // load received data into buffer
657 #ifdef SIO_DEBUG
658                         emu->out_debug_log(_T("Z80SIO: ch=%d recv %2x\n"), ch, data);
659 #endif
660                         port[ch].recv->write(data);
661                         
662                         // quit abort
663                         if(port[ch].abort) {
664                                 port[ch].abort = false;
665                                 if(!port[ch].stat_intr) {
666                                         port[ch].stat_intr = true;
667                                         update_intr_required = true;
668                                 }
669                         }
670                         
671                         // check receive interrupt
672                         bool req = false;
673                         if((port[ch].wr[1] & 0x18) == 8 && (port[ch].first_data || port[ch].nextrecv_intr)) {
674                                 req = true;
675                         } else if(port[ch].wr[1] & 0x10) {
676                                 req = true;
677                         }
678                         if(req) {
679                                 if(port[ch].recv_intr++ == 0) {
680                                         update_intr_required = true;
681                                 }
682                         }
683                         port[ch].first_data = port[ch].nextrecv_intr = false;
684                 }
685 request_next_data:
686                 bool first_data = port[ch].first_data;
687                 if(port[ch].rtmp->empty()) {
688                         // request data in this message
689                         write_signals(&port[ch].outputs_rxdone, 0xffffffff);
690                 }
691                 if(port[ch].rtmp->empty()) {
692                         // no data received
693 #ifdef SIO_DEBUG
694                         emu->out_debug_log(_T("Z80SIO: ch=%d end of block\n"), ch);
695 #endif
696                         port[ch].recv_id = -1;
697                 } else {
698                         REGISTER_RECV_EVENT(ch);
699                         port[ch].first_data = first_data;
700                 }
701                 if(update_intr_required) {
702                         update_intr();
703                 }
704         }
705 }
706
707 void Z80SIO::update_tx_timing(int ch)
708 {
709         port[ch].tx_bits_x2 = (port[ch].wr[4] & 1) * 2;
710         switch(port[ch].wr[5] & 0x60) {
711         case 0x00: port[ch].tx_bits_x2 += 2 * port[ch].tx_data_bits; break;
712         case 0x20: port[ch].tx_bits_x2 += 2 * 7; break;
713         case 0x40: port[ch].tx_bits_x2 += 2 * 6; break;
714         case 0x60: port[ch].tx_bits_x2 += 2 * 8; break;
715         }
716         switch(port[ch].wr[4] & 0x0c) {
717         case 0x00: port[ch].tx_bits_x2 += 0; break;     // sync mode
718         case 0x04: port[ch].tx_bits_x2 += 4; break;     // 2 * (1 + 1)
719         case 0x08: port[ch].tx_bits_x2 += 5; break;     // 2 * (1 + 1.5)
720         case 0x0c: port[ch].tx_bits_x2 += 6; break;     // 2 * (1 + 2)
721         }
722         switch(port[ch].wr[4] & 0xc0) {
723         case 0x40: port[ch].tx_bits_x2 *= 16; break;
724         case 0x80: port[ch].tx_bits_x2 *= 32; break;
725         case 0xc0: port[ch].tx_bits_x2 *= 64; break;
726         }
727         if(port[ch].tx_clock != 0) {
728                 port[ch].tx_interval = 1000000.0 / port[ch].tx_clock * (double)port[ch].tx_bits_x2 / 2.0;
729         }
730 }
731
732 void Z80SIO::update_rx_timing(int ch)
733 {
734         port[ch].rx_bits_x2 = (port[ch].wr[4] & 1) * 2;
735         switch(port[ch].wr[3] & 0xc0) {
736         case 0x00: port[ch].rx_bits_x2 += 2 * 5; break;
737         case 0x40: port[ch].rx_bits_x2 += 2 * 7; break;
738         case 0x80: port[ch].rx_bits_x2 += 2 * 6; break;
739         case 0xc0: port[ch].rx_bits_x2 += 2 * 8; break;
740         }
741         switch(port[ch].wr[4] & 0x0c) {
742         case 0x00: port[ch].rx_bits_x2 += 0; break;     // sync mode
743         case 0x04: port[ch].rx_bits_x2 += 4; break;     // 2 * (1 + 1)
744         case 0x08: port[ch].rx_bits_x2 += 5; break;     // 2 * (1 + 1.5)
745         case 0x0c: port[ch].rx_bits_x2 += 6; break;     // 2 * (1 + 2)
746         }
747         switch(port[ch].wr[4] & 0xc0) {
748         case 0x40: port[ch].rx_bits_x2 *= 16; break;
749         case 0x80: port[ch].rx_bits_x2 *= 32; break;
750         case 0xc0: port[ch].rx_bits_x2 *= 64; break;
751         }
752         if(port[ch].rx_clock != 0) {
753                 port[ch].rx_interval = 1000000.0 / port[ch].rx_clock * (double)port[ch].rx_bits_x2 / 2.0;
754         }
755 }
756
757 void Z80SIO::set_intr_iei(bool val)
758 {
759         if(iei != val) {
760                 iei = val;
761                 update_intr();
762         }
763 }
764
765 #define set_intr_oei(val) { \
766         if(oei != val) { \
767                 oei = val; \
768                 if(d_child) { \
769                         d_child->set_intr_iei(oei); \
770                 } \
771         } \
772 }
773
774 void Z80SIO::update_intr()
775 {
776         bool next;
777         
778         // set oei signal
779         if((next = iei) == true) {
780                 for(int ch = 0; ch < 2; ch++) {
781                         if(port[ch].in_service) {
782                                 next = false;
783                                 break;
784                         }
785                 }
786         }
787         set_intr_oei(next);
788         
789         // check interrupt status
790         for(int ch = 0; ch < 2; ch++) {
791                 if(port[ch].err_intr) {
792                         port[ch].req_intr = true;
793                         port[ch].affect = (ch ? 0 : 4) | 3;
794                 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
795                         port[ch].req_intr = true;
796                         port[ch].affect = (ch ? 0 : 4) | 2;
797                 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
798                         port[ch].req_intr = true;
799                         port[ch].affect = (ch ? 0 : 4) | 1;
800                 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
801                         port[ch].req_intr = true;
802                         port[ch].affect = (ch ? 0 : 4) | 0;
803                 } else {
804                         port[ch].req_intr = false;
805                 }
806         }
807         
808         // create vector
809         if(port[1].wr[1] & 4) {
810 #ifdef HAS_UPD7201
811                 uint8 affect = 7;       // no interrupt pending
812                 for(int ch = 0; ch < 2; ch++) {
813                         if(port[ch].in_service) {
814                                 break;
815                         }
816                         if(port[ch].req_intr) {
817                                 affect = port[ch].affect;
818                                 break;
819                         }
820                 }
821                 uint8 mode = port[0].wr[2] & 0x38;
822                 if(mode == 0 || mode == 8 || mode == 0x20 || mode == 0x28 || mode == 0x38) {
823                         port[1].vector = (port[1].wr[2] & 0xe3) | (affect << 2);        // 8085
824                 } else {
825                         port[1].vector = (port[1].wr[2] & 0xf8) | (affect << 0);        // 8086
826                 }
827 #else
828                 uint8 affect = 3;       // no interrupt pending
829                 for(int ch = 0; ch < 2; ch++) {
830                         if(port[ch].in_service) {
831                                 break;
832                         }
833                         if(port[ch].req_intr) {
834                                 affect = port[ch].affect;
835                                 break;
836                         }
837                 }
838                 port[1].vector = (port[1].wr[2] & 0xf1) | (affect << 1);
839 #endif
840         } else {
841                 port[1].vector = port[1].wr[2];
842         }
843         
844         // set int signal
845         if((next = iei) == true) {
846                 next = false;
847                 for(int ch = 0; ch < 2; ch++) {
848                         if(port[ch].in_service) {
849                                 break;
850                         }
851                         if(port[ch].req_intr) {
852                                 next = true;
853                                 break;
854                         }
855                 }
856         }
857         if(d_cpu) {
858                 d_cpu->set_intr_line(next, true, intr_bit);
859         }
860 }
861
862 uint32 Z80SIO::intr_ack()
863 {
864         // ack (M1=IORQ=L)
865         for(int ch = 0; ch < 2; ch++) {
866                 if(port[ch].in_service) {
867                         // invalid interrupt status
868                         return 0xff;
869                 }
870                 // priority is error > receive > status > send ???
871                 if(port[ch].err_intr) {
872                         port[ch].err_intr = false;
873                         port[ch].in_service = true;
874                 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
875                         port[ch].recv_intr = 0;
876                         port[ch].in_service = true;
877                 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
878                         port[ch].stat_intr = false;
879                         port[ch].in_service = true;
880                 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
881                         port[ch].send_intr = false;
882                         port[ch].in_service = true;
883                 }
884                 if(port[ch].in_service) {
885                         uint8 vector = port[1].vector;
886                         update_intr();
887                         return vector;
888                 }
889         }
890         if(d_child) {
891                 return d_child->intr_ack();
892         }
893         return 0xff;
894 }
895
896 void Z80SIO::intr_reti()
897 {
898         // detect RETI
899         for(int ch = 0; ch < 2; ch++) {
900                 if(port[ch].in_service) {
901                         port[ch].in_service = false;
902                         update_intr();
903                         return;
904                 }
905         }
906         if(d_child) {
907                 d_child->intr_reti();
908         }
909 }
910
911 #define STATE_VERSION   3
912
913 void Z80SIO::save_state(FILEIO* state_fio)
914 {
915         state_fio->FputUint32(STATE_VERSION);
916         state_fio->FputInt32(this_device_id);
917         
918         for(int i = 0; i < 2; i++) {
919                 state_fio->FputInt32(port[i].pointer);
920                 state_fio->Fwrite(port[i].wr, sizeof(port[i].wr), 1);
921                 state_fio->FputUint8(port[i].vector);
922                 state_fio->FputUint8(port[i].affect);
923                 state_fio->FputBool(port[i].nextrecv_intr);
924                 state_fio->FputBool(port[i].first_data);
925                 state_fio->FputBool(port[i].over_flow);
926                 state_fio->FputBool(port[i].under_run);
927                 state_fio->FputBool(port[i].abort);
928                 state_fio->FputBool(port[i].sync);
929                 state_fio->FputUint8(port[i].sync_bit);
930 #ifdef HAS_UPD7201
931                 state_fio->FputUint16(port[i].tx_count);
932                 state_fio->FputUint8(port[i].tx_count_hi);
933 #endif
934                 state_fio->FputDouble(port[i].tx_clock);
935                 state_fio->FputDouble(port[i].tx_interval);
936                 state_fio->FputDouble(port[i].rx_clock);
937                 state_fio->FputDouble(port[i].rx_interval);
938                 state_fio->FputInt32(port[i].tx_data_bits);
939                 state_fio->FputInt32(port[i].tx_bits_x2);
940                 state_fio->FputInt32(port[i].tx_bits_x2_remain);
941                 state_fio->FputInt32(port[i].rx_bits_x2);
942                 state_fio->FputInt32(port[i].rx_bits_x2_remain);
943                 state_fio->FputBool(port[i].prev_tx_clock_signal);
944                 state_fio->FputBool(port[i].prev_rx_clock_signal);
945                 port[i].send->save_state((void *)state_fio);
946                 port[i].recv->save_state((void *)state_fio);
947                 port[i].rtmp->save_state((void *)state_fio);
948                 state_fio->FputInt32(port[i].shift_reg);
949                 state_fio->FputInt32(port[i].send_id);
950                 state_fio->FputInt32(port[i].recv_id);
951                 state_fio->FputBool(port[i].err_intr);
952                 state_fio->FputInt32(port[i].recv_intr);
953                 state_fio->FputBool(port[i].stat_intr);
954                 state_fio->FputBool(port[i].send_intr);
955                 state_fio->FputBool(port[i].req_intr);
956                 state_fio->FputBool(port[i].in_service);
957                 state_fio->FputBool(port[i].dcd);
958                 state_fio->FputBool(port[i].cts);
959         }
960         state_fio->FputBool(iei);
961         state_fio->FputBool(oei);
962         state_fio->FputUint32(intr_bit);
963 }
964
965 bool Z80SIO::load_state(FILEIO* state_fio)
966 {
967         if(state_fio->FgetUint32() != STATE_VERSION) {
968                 return false;
969         }
970         if(state_fio->FgetInt32() != this_device_id) {
971                 return false;
972         }
973         for(int i = 0; i < 2; i++) {
974                 port[i].pointer = state_fio->FgetInt32();
975                 state_fio->Fread(port[i].wr, sizeof(port[i].wr), 1);
976                 port[i].vector = state_fio->FgetUint8();
977                 port[i].affect = state_fio->FgetUint8();
978                 port[i].nextrecv_intr = state_fio->FgetBool();
979                 port[i].first_data = state_fio->FgetBool();
980                 port[i].over_flow = state_fio->FgetBool();
981                 port[i].under_run = state_fio->FgetBool();
982                 port[i].abort = state_fio->FgetBool();
983                 port[i].sync = state_fio->FgetBool();
984                 port[i].sync_bit = state_fio->FgetUint8();
985 #ifdef HAS_UPD7201
986                 port[i].tx_count = state_fio->FgetUint16();
987                 port[i].tx_count_hi = state_fio->FgetUint8();
988 #endif
989                 port[i].tx_clock = state_fio->FgetDouble();
990                 port[i].tx_interval = state_fio->FgetDouble();
991                 port[i].rx_clock = state_fio->FgetDouble();
992                 port[i].rx_interval = state_fio->FgetDouble();
993                 port[i].tx_data_bits = state_fio->FgetInt32();
994                 port[i].tx_bits_x2 = state_fio->FgetInt32();
995                 port[i].tx_bits_x2_remain = state_fio->FgetInt32();
996                 port[i].rx_bits_x2 = state_fio->FgetInt32();
997                 port[i].rx_bits_x2_remain = state_fio->FgetInt32();
998                 port[i].prev_tx_clock_signal = state_fio->FgetBool();
999                 port[i].prev_rx_clock_signal = state_fio->FgetBool();
1000                 if(!port[i].send->load_state((void *)state_fio)) {
1001                         return false;
1002                 }
1003                 if(!port[i].recv->load_state((void *)state_fio)) {
1004                         return false;
1005                 }
1006                 if(!port[i].rtmp->load_state((void *)state_fio)) {
1007                         return false;
1008                 }
1009                 port[i].shift_reg = state_fio->FgetInt32();
1010                 port[i].send_id = state_fio->FgetInt32();
1011                 port[i].recv_id = state_fio->FgetInt32();
1012                 port[i].err_intr = state_fio->FgetBool();
1013                 port[i].recv_intr = state_fio->FgetInt32();
1014                 port[i].stat_intr = state_fio->FgetBool();
1015                 port[i].send_intr = state_fio->FgetBool();
1016                 port[i].req_intr = state_fio->FgetBool();
1017                 port[i].in_service = state_fio->FgetBool();
1018                 port[i].dcd = state_fio->FgetBool();
1019                 port[i].cts = state_fio->FgetBool();
1020         }
1021         iei = state_fio->FgetBool();
1022         oei = state_fio->FgetBool();
1023         intr_bit = state_fio->FgetUint32();
1024         return true;
1025 }
1026