OSDN Git Service

[VM] MEMORY:: class within some VM will change Foo_MEMORY:: to reduce misundestanding...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr30 / serial.cpp
1 /*
2         FUJITSU FMR-30 Emulator 'eFMR-30'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.12.31 -
6
7         [ serial ]
8 */
9
10 #include "serial.h"
11 #include "../i8251.h"
12 #include "../i8259.h"
13
14 void SERIAL::initialize()
15 {
16         memset(sioctrl, sizeof(sioctrl), 1);
17 }
18
19 void SERIAL::write_io8(uint32_t addr, uint32_t data)
20 {
21         switch(addr & 0xffff) {
22         case 0x0a:
23                 sioctrl[0].baud = data;
24                 break;
25         case 0x0b:
26                 sioctrl[0].ctrl = data;
27                 d_kb->write_signal(SIG_I8251_LOOPBACK, data, 8);
28                 update_intr(0);
29                 break;
30         case 0x12:
31                 sioctrl[1].baud = data;
32                 break;
33         case 0x13:
34                 sioctrl[1].ctrl = data;
35                 d_sub->write_signal(SIG_I8251_LOOPBACK, data, 8);
36                 update_intr(1);
37                 break;
38         case 0x62:
39                 sioctrl[2].baud = data;
40                 break;
41         case 0x63:
42                 sioctrl[2].ctrl = data;
43                 d_ch1->write_signal(SIG_I8251_LOOPBACK, data, 8);
44                 update_intr(2);
45                 break;
46         case 0x64:
47                 sioctrl[2].intmask = data;
48                 break;
49         case 0x65:
50                 sioctrl[2].intstat &= ~data;
51                 break;
52         case 0x72:
53                 sioctrl[3].baud = data;
54                 break;
55         case 0x73:
56                 sioctrl[3].ctrl = data;
57                 d_ch2->write_signal(SIG_I8251_LOOPBACK, data, 8);
58                 update_intr(3);
59                 break;
60         case 0x74:
61                 sioctrl[3].intmask = data;
62                 break;
63         case 0x75:
64                 sioctrl[3].intstat &= ~data;
65                 break;
66         }
67 }
68
69 uint32_t SERIAL::read_io8(uint32_t addr)
70 {
71         switch(addr & 0xffff) {
72         case 0x0a:
73                 return sioctrl[0].baud;
74         case 0x0b:
75                 return sioctrl[0].ctrl;
76         case 0x12:
77                 return sioctrl[1].baud;
78         case 0x13:
79                 return sioctrl[1].ctrl;
80         case 0x62:
81                 return sioctrl[2].baud;
82         case 0x63:
83                 return sioctrl[2].ctrl;
84         case 0x64:
85                 return sioctrl[2].intmask;
86         case 0x65:
87                 return sioctrl[2].intstat;
88         case 0x66:
89                 return 0xf0;    // append register
90         case 0x72:
91                 return sioctrl[3].baud;
92         case 0x73:
93                 return sioctrl[3].ctrl;
94         case 0x74:
95                 return sioctrl[3].intmask;
96         case 0x75:
97                 return sioctrl[3].intstat;
98         case 0x76:
99                 return 0xf0;    // append register
100         }
101         return 0xff;
102 }
103
104 void SERIAL::write_signal(int id, uint32_t data, uint32_t mask)
105 {
106         switch(id) {
107         case SIG_SERIAL_RXRDY_KB:
108         case SIG_SERIAL_RXRDY_SUB:
109         case SIG_SERIAL_RXRDY_CH1:
110         case SIG_SERIAL_RXRDY_CH2:
111                 sioctrl[id & 3].rxrdy = ((data & mask) != 0);
112                 update_intr(id & 3);
113                 break;
114         case SIG_SERIAL_TXRDY_KB:
115         case SIG_SERIAL_TXRDY_SUB:
116         case SIG_SERIAL_TXRDY_CH1:
117         case SIG_SERIAL_TXRDY_CH2:
118                 sioctrl[id & 3].txrdy = ((data & mask) != 0);
119                 update_intr(id & 3);
120                 break;
121         }
122 }
123
124 void SERIAL::update_intr(int ch)
125 {
126         static const int pic_ids[4] = {
127                 SIG_I8259_CHIP0 | SIG_I8259_IR2,        // keyboard
128                 SIG_I8259_CHIP0 | SIG_I8259_IR3,        // sub
129                 SIG_I8259_CHIP0 | SIG_I8259_IR4,        // rs-232c ch.1
130                 SIG_I8259_CHIP1 | SIG_I8259_IR4         // rs-232c ch.2
131         };
132         
133         if((sioctrl[ch].rxrdy && (sioctrl[ch].ctrl & 0x40)) || (sioctrl[ch].txrdy && (sioctrl[ch].ctrl & 0x20))) {
134                 d_pic->write_signal(pic_ids[ch], 1, 1);
135                 sioctrl[ch].intstat |=  4;
136         } else {
137                 d_pic->write_signal(pic_ids[ch], 0, 1);
138                 sioctrl[ch].intstat &=  ~4;
139         }
140 }
141
142 #define STATE_VERSION   1
143
144 bool SERIAL::process_state(FILEIO* state_fio, bool loading)
145 {
146         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
147                 return false;
148         }
149         if(!state_fio->StateCheckInt32(this_device_id)) {
150                 return false;
151         }
152         //state_fio->StateBuffer(sioctrl, sizeof(sioctrl), 1);
153         for(int i = 0; i < 4; i++) {
154                 state_fio->StateUint8(sioctrl[i].baud);
155                 state_fio->StateUint8(sioctrl[i].ctrl);
156                 state_fio->StateBool(sioctrl[i].rxrdy);
157                 state_fio->StateBool(sioctrl[i].txrdy);
158                 state_fio->StateUint8(sioctrl[i].intmask);
159                 state_fio->StateUint8(sioctrl[i].intstat);
160         }
161         return true;
162 }