OSDN Git Service

[VM][DEVICE][I386] Add bios_call_far_ia32() and bios_int_ia32() because BIOS calling...
[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         DEVICE::initialize();
88         __HAS_UPD7201 = osd->check_feature(_T("HAS_UPD7201"));
89         __SIO_DEBUG   = osd->check_feature(_T("SIO_DEBUG"));
90         
91         for(int ch = 0; ch < 2; ch++) {
92 //#ifdef HAS_UPD7201
93                 if(__HAS_UPD7201) {
94                         port[ch].send = new FIFO(16);
95                         port[ch].recv = new FIFO(16);
96                         port[ch].rtmp = new FIFO(16);
97                 } else {
98 //#else
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;
103                 }
104 //#endif
105                 // input signals
106                 port[ch].dcd = true;
107                 port[ch].cts = true;
108                 port[ch].sync = true;
109                 port[ch].sync_bit = 0;
110         }
111 }
112
113 void Z80SIO::reset()
114 {
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;
122 //#ifdef HAS_UPD7201
123                 port[ch].tx_count = 0;
124 //#endif
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));
132                 // interrupt
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;
139         }
140         iei = oei = true;
141 }
142
143 void Z80SIO::release()
144 {
145         for(int ch = 0; ch < 2; ch++) {
146                 if(port[ch].send) {
147                         port[ch].send->release();
148                         delete port[ch].send;
149                 }
150                 if(port[ch].recv) {
151                         port[ch].recv->release();
152                         delete port[ch].recv;
153                 }
154                 if(port[ch].rtmp) {
155                         port[ch].rtmp->release();
156                         delete port[ch].rtmp;
157                 }
158         }
159 }
160
161 /*
162         0       ch.a data
163         1       ch.a control
164         2       ch.b data
165         3       ch.b control
166 */
167
168 void Z80SIO::write_io8(uint32_t addr, uint32_t data)
169 {
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;
174         
175         switch(addr & 3) {
176         case 0:
177         case 2:
178                 // send data
179                 if(port[ch].send_intr) {
180                         port[ch].send_intr = false;
181                         update_intr();
182                 }
183                 // register next event
184                 if(port[ch].wr[5] & 8) {
185                         int tx_data_bits = 5;
186                         if((data & 0xe0) == 0x00) {
187                                 tx_data_bits = 5;
188                         } else if((data & 0xf0) == 0x80) {
189                                 tx_data_bits = 4;
190                         } else if((data & 0xf8) == 0xc0) {
191                                 tx_data_bits = 3;
192                         } else if((data & 0xfc) == 0xe0) {
193                                 tx_data_bits = 2;
194                         } else if((data & 0xfe) == 0xf0) {
195                                 tx_data_bits = 1;
196                         }
197                         if(port[ch].tx_data_bits != tx_data_bits) {
198                                 port[ch].tx_data_bits = tx_data_bits;
199                                 update_tx_timing(ch);
200                         }
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);
205                         } else {
206                                 REGISTER_SEND_EVENT(ch);
207                         }
208                 } else {
209                         CANCEL_SEND_EVENT(ch);
210                 }
211 //#ifndef HAS_UPD7201
212                 if(!__HAS_UPD7201) port[ch].send->clear();
213 //#endif
214                 port[ch].send->write(data);
215 //#ifdef HAS_UPD7201
216                 if(__HAS_UPD7201) port[ch].tx_count++;
217 //#endif
218                 break;
219         case 1:
220         case 3:
221                 // control
222 //#ifdef SIO_DEBUG
223 //              if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d WR[%d]=%2x\n"), ch, port[ch].pointer, data);
224 //#endif
225                 switch(port[ch].pointer) {
226                 case 0:
227                         switch(data & 0x38) {
228                         case 0x10:
229                                 if(port[ch].stat_intr) {
230                                         port[ch].stat_intr = false;
231                                         update_intr_required = true;
232                                 }
233                                 break;
234                         case 0x18:
235                                 // channel reset
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;
241 //#ifdef HAS_UPD7201
242                                 if(__HAS_UPD7201) port[ch].tx_count = 0;        // is this correct ???
243 //#endif
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));
249                                 // interrupt
250                                 if(port[ch].err_intr) {
251                                         port[ch].err_intr = false;
252                                         update_intr_required = true;
253                                 }
254                                 if(port[ch].recv_intr) {
255                                         port[ch].recv_intr = 0;
256                                         update_intr_required = true;
257                                 }
258                                 if(port[ch].stat_intr) {
259                                         port[ch].stat_intr = false;
260                                         update_intr_required = true;
261                                 }
262                                 if(port[ch].send_intr) {
263                                         port[ch].send_intr = false;
264                                         update_intr_required = true;
265                                 }
266                                 port[ch].req_intr = false;
267                                 break;
268                         case 0x20:
269                                 port[ch].nextrecv_intr = true;
270                                 break;
271                         case 0x28:
272                                 if(port[ch].send_intr) {
273                                         port[ch].send_intr = false;
274                                         update_intr_required = true;
275                                 }
276                                 break;
277                         case 0x30:
278                                 port[ch].over_flow = false;
279                                 if(port[ch].err_intr) {
280                                         port[ch].err_intr = false;
281                                         update_intr_required = true;
282                                 }
283                                 break;
284                         case 0x38:
285                                 // end of interrupt
286                                 if(ch == 0) {
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;
291                                                         break;
292                                                 }
293                                         }
294                                 }
295                                 break;
296                         }
297                         switch(data & 0xc0) {
298                         case 0x40:
299                                 // reset receive crc checker
300                                 break;
301                         case 0x80:
302                                 // reset transmit crc generator
303                                 break;
304                         case 0xc0:
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;
311                                         }
312                                 }
313                                 break;
314                         }
315                         break;
316                 case 1:
317                 case 2:
318                         if(port[ch].wr[port[ch].pointer] != data) {
319                                 update_intr_required = true;
320                         }
321                         break;
322                 case 3:
323                         if((data & 0x11) == 0x11) {
324                                 // enter hunt/sync phase
325                                 if(MONOSYNC(ch)) {
326 //#ifdef SIO_DEBUG
327                                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (monosync)\n"), ch);
328 //#endif
329                                         port[ch].sync_bit = BIT_SYNC1;
330                                 } else if(BISYNC(ch)) {
331 //#ifdef SIO_DEBUG
332                                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (bisync)\n"), ch);
333 //#endif
334                                         port[ch].sync_bit = BIT_SYNC1 | BIT_SYNC2;
335                                 }
336                                 port[ch].sync = false;
337                                 write_signals(&port[ch].outputs_sync, 0xffffffff);
338                         }
339                         if((port[ch].wr[3] & 0xc0) != (data & 0xc0)) {
340                                 update_rx_timing_required = true;
341                         }
342                         break;
343                 case 4:
344                         if((port[ch].wr[4] & 0xcd) != (data & 0xcd)) {
345                                 update_tx_timing_required = update_rx_timing_required = true;
346                         }
347                         break;
348                 case 5:
349                         if((uint32_t)(port[ch].wr[5] & 2) != (data & 2)) {
350                                 // rts
351                                 write_signals(&port[ch].outputs_rts, (data & 2) ? 0 : 0xffffffff);
352                         }
353                         if((uint32_t)(port[ch].wr[5] & 0x80) != (data & 0x80)) {
354                                 // dtr
355                                 write_signals(&port[ch].outputs_dtr, (data & 0x80) ? 0 : 0xffffffff);
356                         }
357                         if(data & 8) {
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);
361                                 } else {
362                                         REGISTER_SEND_EVENT(ch);
363                                 }
364                         } else {
365                                 CANCEL_SEND_EVENT(ch);
366                         }
367                         if(data & 0x10) {
368                                 // send break
369                                 write_signals(&port[ch].outputs_break, 0xffffffff);
370                         }
371                         if((port[ch].wr[5] & 0x60) != (data & 0x60)) {
372                                 update_tx_timing_required = true;
373                         }
374                         break;
375                 }
376                 port[ch].wr[port[ch].pointer] = data;
377                 if(update_intr_required) {
378                         update_intr();
379                 }
380                 if(update_tx_timing_required) {
381                         update_tx_timing(ch);
382                 }
383                 if(update_rx_timing_required) {
384                         update_rx_timing(ch);
385                 }
386                 port[ch].pointer = (port[ch].pointer == 0) ? (data & 7) : 0;
387                 break;
388         }
389 }
390
391 uint32_t Z80SIO::read_io8(uint32_t addr)
392 {
393         int ch = (addr >> 1) & 1;
394         uint32_t val = 0;
395         
396         switch(addr & 3) {
397         case 0:
398         case 2:
399                 // recv data;
400                 if(port[ch].recv_intr) {
401                         // cancel pending interrupt
402                         if(--port[ch].recv_intr == 0) {
403                                 update_intr();
404                         }
405                 }
406                 return port[ch].recv->read();
407         case 1:
408         case 3:
409                 if(port[ch].pointer == 0) {
410                         if(!port[ch].recv->empty()) {
411                                 val |= 1;
412                         }
413                         if(ch == 0 && (port[0].req_intr || port[1].req_intr)) {
414                                 val |= 2;
415                         }
416                         if(!port[ch].send->full()) {
417                                 val |= 4;       // ???
418                         }
419                         if(!port[ch].dcd) {
420                                 val |= 8;
421                         }
422                         if(!port[ch].sync) {
423                                 val |= 0x10;
424                         }
425                         if(!port[ch].cts) {
426                                 val |= 0x20;
427                         }
428                         if(port[ch].under_run) {
429                                 val |= 0x40;
430                         }
431                         if(port[ch].abort) {
432                                 val |= 0x80;
433                         }
434                 } else if(port[ch].pointer == 1) {
435                         val = 0x8e;     // TODO
436                         if(port[ch].send->empty()) {
437                                 val |= 1;
438                         }
439                         if(port[ch].over_flow) {
440                                 val |= 0x20;
441                         }
442                 } else if(port[ch].pointer == 2) {
443                         val = port[ch].vector;
444 //#ifdef HAS_UPD7201
445                 } else if(port[ch].pointer == 3) {
446                         if(__HAS_UPD7201) {
447                                 val = port[ch].tx_count & 0xff;
448                                 port[ch].tx_count_hi = port[ch].tx_count >> 8;
449                         }
450                 } else if(port[ch].pointer == 4) {
451                         if(__HAS_UPD7201) {
452 //                      val = (port[ch].tx_count >> 8) & 0xff;
453                                 val = port[ch].tx_count_hi;
454                         }
455 //#endif
456                 }
457                 port[ch].pointer = 0;
458                 return val;
459         }
460         return 0xff;
461 }
462
463 void Z80SIO::write_signal(int id, uint32_t data, uint32_t mask)
464 {
465         // recv data
466         int ch = id & 1;
467         bool signal = ((data & mask) != 0);
468         
469         switch(id) {
470         case SIG_Z80SIO_RECV_CH0:
471         case SIG_Z80SIO_RECV_CH1:
472                 // recv data
473                 REGISTER_RECV_EVENT(ch);
474                 if(port[ch].rtmp->empty()) {
475                         port[ch].first_data = true;
476                 }
477                 port[ch].rtmp->write(data & mask);
478                 break;
479         case SIG_Z80SIO_BREAK_CH0:
480         case SIG_Z80SIO_BREAK_CH1:
481                 // recv break
482                 if((data & mask) && !port[ch].abort) {
483                         port[ch].abort = true;
484                         if(!port[ch].stat_intr) {
485                                 port[ch].stat_intr = true;
486                                 update_intr();
487                         }
488                 }
489                 break;
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)) {
495                                 // auto enables
496                                 port[ch].wr[3] |= 1;
497                         }
498                         if(!port[ch].stat_intr) {
499                                 port[ch].stat_intr = true;
500                                 update_intr();
501                         }
502                 }
503                 break;
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)) {
509                                 // auto enables
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);
513                                 } else {
514                                         REGISTER_SEND_EVENT(ch);
515                                 }
516                                 port[ch].wr[5] |= 8;
517                         }
518                         if(!port[ch].stat_intr) {
519                                 port[ch].stat_intr = true;
520                                 update_intr();
521                         }
522                 }
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;
529                                 update_intr();
530                         }
531                 }
532                 break;
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);
538                         }
539                         port[ch].prev_tx_clock_signal = signal;
540                 }
541                 break;
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);
547                         }
548                         port[ch].prev_rx_clock_signal = signal;
549                 }
550                 break;
551         case SIG_Z80SIO_CLEAR_CH0:
552         case SIG_Z80SIO_CLEAR_CH1:
553                 // hack: clear recv buffer
554                 if(data & mask) {
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;
560                                 update_intr();
561                         }
562                 }
563                 break;
564         }
565 }
566
567 void Z80SIO::event_callback(int event_id, int err)
568 {
569         int ch = event_id & 1;
570         
571         if(event_id & EVENT_SEND) {
572                 // send
573                 port[ch].send_id = -1;
574                 port[ch].tx_bits_x2_remain = 0;
575                 
576                 bool under_run = true;
577                 
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;
582                         under_run = false;
583                 }
584                 if(!port[ch].send->empty()) {
585                         // load data in send buffer to shift register
586                         port[ch].shift_reg = port[ch].send->read();
587                         under_run = false;
588                 }
589                 if(under_run) {
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;
595                                         update_intr();
596                                 }
597                         }
598                 }
599                 if(port[ch].send->empty()) {
600                         // transmitter interrupt
601                         if(!port[ch].send_intr) {
602                                 port[ch].send_intr = true;
603                                 update_intr();
604                         }
605                         write_signals(&port[ch].outputs_txdone, 0xffffffff);
606                 }
607                 REGISTER_SEND_EVENT(ch);
608         } else if(event_id & EVENT_RECV) {
609                 // recv
610                 port[ch].recv_id = -1;
611                 port[ch].rx_bits_x2_remain = 0;
612                 
613                 if(!(port[ch].wr[3] & 1)) {
614                         REGISTER_RECV_EVENT(ch);
615                         return;
616                 }
617                 bool update_intr_required = false;
618                 
619                 if(port[ch].recv->full()) {
620                         // overflow
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;
626                                 }
627                         }
628                 } else {
629                         // no error
630                         int data = port[ch].rtmp->read();
631                         
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;
637                                         }
638 //#ifdef SIO_DEBUG
639                                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv sync1\n"), ch);
640 //#endif
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;
646                                         }
647 //#ifdef SIO_DEBUG
648                                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv sync2\n"), ch);
649 //#endif
650                                         port[ch].sync_bit &= ~BIT_SYNC2;
651                                 }
652                                 if(port[ch].sync_bit == 0) {
653 //#ifdef SIO_DEBUG
654                                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d leave hunt/sync phase\n"), ch);
655 //#endif
656                                         if(!port[ch].stat_intr) {
657                                                 port[ch].stat_intr = true;
658                                                 update_intr_required = true;
659                                         }
660                                         port[ch].sync = true;
661                                         write_signals(&port[ch].outputs_sync, 0);
662                                 }
663                                 if(port[ch].wr[3] & 2) {
664                                         // sync char is not loaded into buffer
665                                         goto request_next_data;
666                                 }
667                         }
668                         // load received data into buffer
669 //#ifdef SIO_DEBUG
670                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d recv %2x\n"), ch, data);
671 //#endif
672                         port[ch].recv->write(data);
673                         
674                         // quit abort
675                         if(port[ch].abort) {
676                                 port[ch].abort = false;
677                                 if(!port[ch].stat_intr) {
678                                         port[ch].stat_intr = true;
679                                         update_intr_required = true;
680                                 }
681                         }
682                         
683                         // check receive interrupt
684                         bool req = false;
685                         if((port[ch].wr[1] & 0x18) == 8 && (port[ch].first_data || port[ch].nextrecv_intr)) {
686                                 req = true;
687                         } else if(port[ch].wr[1] & 0x10) {
688                                 req = true;
689                         }
690                         if(req) {
691                                 if(port[ch].recv_intr++ == 0) {
692                                         update_intr_required = true;
693                                 }
694                         }
695                         port[ch].first_data = port[ch].nextrecv_intr = false;
696                 }
697 request_next_data:
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);
702                 }
703                 if(port[ch].rtmp->empty()) {
704                         // no data received
705 //#ifdef SIO_DEBUG
706                         if(__SIO_DEBUG) this->out_debug_log(_T("Z80SIO: ch=%d end of block\n"), ch);
707 //#endif
708                         port[ch].recv_id = -1;
709                 } else {
710                         REGISTER_RECV_EVENT(ch);
711                         port[ch].first_data = first_data;
712                 }
713                 if(update_intr_required) {
714                         update_intr();
715                 }
716         }
717 }
718
719 void Z80SIO::update_tx_timing(int ch)
720 {
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;
727         }
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)
733         }
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;
738         }
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;
741         }
742 }
743
744 void Z80SIO::update_rx_timing(int ch)
745 {
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;
752         }
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)
758         }
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;
763         }
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;
766         }
767 }
768
769 void Z80SIO::set_intr_iei(bool val)
770 {
771         if(iei != val) {
772                 iei = val;
773                 update_intr();
774         }
775 }
776
777 #define set_intr_oei(val) { \
778         if(oei != val) { \
779                 oei = val; \
780                 if(d_child) { \
781                         d_child->set_intr_iei(oei); \
782                 } \
783         } \
784 }
785
786 void Z80SIO::update_intr()
787 {
788         bool next;
789         
790         // set oei signal
791         if((next = iei) == true) {
792                 for(int ch = 0; ch < 2; ch++) {
793                         if(port[ch].in_service) {
794                                 next = false;
795                                 break;
796                         }
797                 }
798         }
799         set_intr_oei(next);
800         
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;
815                 } else {
816                         port[ch].req_intr = false;
817                 }
818         }
819         
820         // create vector
821         if(port[1].wr[1] & 4) {
822 //#ifdef HAS_UPD7201
823                 if(__HAS_UPD7201) {
824                         uint8_t affect = 7;     // no interrupt pending
825                         for(int ch = 0; ch < 2; ch++) {
826                                 if(port[ch].in_service) {
827                                         break;
828                                 }
829                                 if(port[ch].req_intr) {
830                                         affect = port[ch].affect;
831                                         break;
832                                 }
833                         }
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
837                         } else {
838                                 port[1].vector = (port[1].wr[2] & 0xf8) | (affect << 0);        // 8086
839                         }
840                 } else {
841 //#else
842                         uint8_t affect = 3;     // no interrupt pending
843                         for(int ch = 0; ch < 2; ch++) {
844                                 if(port[ch].in_service) {
845                                         break;
846                                 }
847                                 if(port[ch].req_intr) {
848                                         affect = port[ch].affect;
849                                         break;
850                                 }
851                         }
852                         port[1].vector = (port[1].wr[2] & 0xf1) | (affect << 1);
853                 }
854 //#endif
855         } else {
856                 port[1].vector = port[1].wr[2];
857         }
858         
859         // set int signal
860         if((next = iei) == true) {
861                 next = false;
862                 for(int ch = 0; ch < 2; ch++) {
863                         if(port[ch].in_service) {
864                                 break;
865                         }
866                         if(port[ch].req_intr) {
867                                 next = true;
868                                 break;
869                         }
870                 }
871         }
872         if(d_cpu) {
873                 d_cpu->set_intr_line(next, true, intr_bit);
874         }
875 }
876
877 uint32_t Z80SIO::get_intr_ack()
878 {
879         // ack (M1=IORQ=L)
880         for(int ch = 0; ch < 2; ch++) {
881                 if(port[ch].in_service) {
882                         // invalid interrupt status
883                         return 0xff;
884                 }
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;
898                 }
899                 if(port[ch].in_service) {
900                         uint8_t vector = port[1].vector;
901                         update_intr();
902                         return vector;
903                 }
904         }
905         if(d_child) {
906                 return d_child->get_intr_ack();
907         }
908         return 0xff;
909 }
910
911 void Z80SIO::notify_intr_reti()
912 {
913         // detect RETI
914         for(int ch = 0; ch < 2; ch++) {
915                 if(port[ch].in_service) {
916                         port[ch].in_service = false;
917                         update_intr();
918                         return;
919                 }
920         }
921         if(d_child) {
922                 d_child->notify_intr_reti();
923         }
924 }
925
926 #define STATE_VERSION   3
927
928 bool Z80SIO::process_state(FILEIO* state_fio, bool loading)
929 {
930         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
931                 return false;
932         }
933         if(!state_fio->StateCheckInt32(this_device_id)) {
934                 return false;
935         }
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);
948                 if(__HAS_UPD7201) {
949                 state_fio->StateValue(port[i].tx_count);
950                 state_fio->StateValue(port[i].tx_count_hi);
951                 }
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)) {
964                         return false;
965                 }
966                 if(!port[i].recv->process_state((void *)state_fio, loading)) {
967                         return false;
968                 }
969                 if(!port[i].rtmp->process_state((void *)state_fio, loading)) {
970                         return false;
971                 }
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);
983         }
984         state_fio->StateValue(iei);
985         state_fio->StateValue(oei);
986         state_fio->StateValue(intr_bit);
987         return true;
988 }
989
990