OSDN Git Service

7423ed266333006363a117d2f3a8bf0b7d6dd271
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr30 / scsi.cpp
1 /*
2         FUJITSU FMR-30 Emulator 'eFMR-30'
3
4         Author : Takeda.Toshiya
5         Date   : 2016.03.04-
6
7         [ scsi ]
8 */
9
10 #include "../vm.h"
11 #include "../../emu.h"
12 #include "scsi.h"
13 #include "../i8237.h"
14 #include "../i8259.h"
15 #include "../scsi_host.h"
16
17 // control register
18 #define CTRL_SWEN       0x80
19 #define CTRL_IMSK       0x40
20 #define CTRL_ATN        0x10
21 #define CTRL_SEL        0x04
22 #define CTRL_DMAE       0x02
23 #define CTRL_RSTS       0x01
24
25 #define STATUS_REQ      0x80
26 #define STATUS_IO       0x40
27 #define STATUS_MSG      0x20
28 #define STATUS_CD       0x10
29 #define STATUS_BSY      0x08
30 #define STATUS_INT      0x02
31 #define STATUS_PERR     0x01
32
33 #define IMSK_PHASE      0x02
34 #define IMSK_EOP        0x01
35
36 #define STATUS_PHASE    0x02
37 #define STATUS_EOP      0x01
38
39 void SCSI::reset()
40 {
41         ctrl_reg = 0;
42         intm_reg = IMSK_PHASE; // DMA terminal count IRQ is disabled
43         phase_status = eop_status = false;
44 }
45
46 void SCSI::write_io8(uint32_t addr, uint32_t data)
47 {
48         switch(addr & 0xffff) {
49         case 0x2f0:
50                 // data register
51                 #ifdef _SCSI_DEBUG_LOG
52                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
53                 #endif
54 //              if(ctrl_reg & CTRL_SWEN) {
55                         d_host->write_dma_io8(addr, data);
56 //              }
57                 break;
58                 
59         case 0x2f1:
60                 // control register
61                 #ifdef _SCSI_DEBUG_LOG
62                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
63                 #endif
64                 ctrl_reg = data;
65 //              if(ctrl_reg  & CTRL_SWEN) {
66                         d_host->write_signal(SIG_SCSI_RST, data, CTRL_RSTS);
67                         d_host->write_signal(SIG_SCSI_SEL, data, CTRL_SEL);
68                         d_host->write_signal(SIG_SCSI_ATN, data, CTRL_ATN);
69 //              }
70                 break;
71                 
72         case 0x2f2:
73                 #ifdef _SCSI_DEBUG_LOG
74                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
75                 #endif
76                 if(data & STATUS_PHASE) {
77                         phase_status = false;
78                 }
79                 if(data & STATUS_EOP) {
80                         eop_status = false;
81                 }
82                 if(!(phase_status || eop_status)) {
83 //                      d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, 0, 0);
84                 }
85                 break;
86                 
87         case 0x2f3:
88                 // irq mask register
89                 #ifdef _SCSI_DEBUG_LOG
90                         this->out_debug_log(_T("[SCSI] out %04X %02X\n"), addr, data);
91                 #endif
92                 intm_reg = data;
93                 break;
94         }
95 }
96
97 uint32_t SCSI::read_io8(uint32_t addr)
98 {
99         uint32_t value = 0;
100         
101         switch(addr & 0xffff) {
102         case 0x2f0:
103                 // data register
104 //              if(ctrl_reg & CTRL_SWEN) {
105                         value = d_host->read_dma_io8(addr);
106 //              }
107                 #ifdef _SCSI_DEBUG_LOG
108                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
109                 #endif
110                 return value;
111                 
112         case 0x2f1:
113                 // status register
114                 value = (d_host->read_signal(SIG_SCSI_REQ) ? STATUS_REQ : 0) |
115                         (d_host->read_signal(SIG_SCSI_IO ) ? STATUS_IO  : 0) |
116                         (d_host->read_signal(SIG_SCSI_MSG) ? STATUS_MSG : 0) |
117                         (d_host->read_signal(SIG_SCSI_CD ) ? STATUS_CD  : 0) |
118                         (d_host->read_signal(SIG_SCSI_BSY) ? STATUS_BSY : 0) |
119                         (phase_status || eop_status        ? STATUS_INT : 0) | 0x04;
120                 #ifdef _SCSI_DEBUG_LOG
121                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
122                 #endif
123                 return value;
124                 
125         case 0x2f2:
126                 // irq status register
127                 value = (phase_status ? STATUS_PHASE : 0) | (eop_status ? STATUS_EOP : 0);
128                 #ifdef _SCSI_DEBUG_LOG
129                         this->out_debug_log(_T("[SCSI] in  %04X %02X\n"), addr, value);
130                 #endif
131                 return value;
132         }
133         return 0xff;
134 }
135
136 void SCSI::write_signal(int id, uint32_t data, uint32_t mask)
137 {
138         switch(id) {
139         case SIG_SCSI_IRQ:
140                 if(ctrl_reg & CTRL_IMSK) {
141                         if(intm_reg & IMSK_PHASE) {
142                                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
143                         }
144                 }
145                 phase_status = ((data & mask) != 0);
146                 break;
147                 
148         case SIG_SCSI_DRQ:
149                 if(ctrl_reg & CTRL_DMAE) {
150                         d_dma->write_signal(SIG_I8237_CH1, data, mask);
151                 }
152                 break;
153                 
154         case SIG_SCSI_TC:
155                 if(ctrl_reg & CTRL_IMSK) {
156                         if(intm_reg & IMSK_EOP) {
157                                 d_pic->write_signal(SIG_I8259_CHIP1 | SIG_I8259_IR2, data, mask);
158                         }
159                 }
160                 eop_status = ((data & mask) != 0);
161                 break;
162         }
163 }
164
165 #define STATE_VERSION   1
166
167 #include "../../statesub.h"
168
169 void SCSI::decl_state()
170 {
171         enter_decl_state(STATE_VERSION);
172
173         DECL_STATE_ENTRY_UINT8(ctrl_reg);
174         DECL_STATE_ENTRY_UINT8(intm_reg);
175         DECL_STATE_ENTRY_BOOL(phase_status);
176         DECL_STATE_ENTRY_BOOL(eop_status);
177         
178         leave_decl_state();
179 }
180
181 void SCSI::save_state(FILEIO* state_fio)
182 {
183         if(state_entry != NULL) {
184                 state_entry->save_state(state_fio);
185         }
186
187 //      state_fio->FputUint32(STATE_VERSION);
188 //      state_fio->FputInt32(this_device_id);
189         
190 //      state_fio->FputUint8(ctrl_reg);
191 //      state_fio->FputUint8(intm_reg);
192 //      state_fio->FputBool(phase_status);
193 //      state_fio->FputBool(eop_status);
194 }
195
196 bool SCSI::load_state(FILEIO* state_fio)
197 {
198         bool mb = false;
199         if(state_entry != NULL) {
200                 mb = state_entry->load_state(state_fio);
201         }
202         if(!mb) {
203                 return false;
204         }
205
206 //      if(state_fio->FgetUint32() != STATE_VERSION) {
207 //              return false;
208 //      }
209 //      if(state_fio->FgetInt32() != this_device_id) {
210 //              return false;
211 //      }
212 //      ctrl_reg = state_fio->FgetUint8();
213 //      intm_reg = state_fio->FgetUint8();
214 //      phase_status = state_fio->FgetBool();
215 //      eop_status = state_fio->FgetBool();
216         return true;
217 }
218
219 bool SCSI::process_state(FILEIO* state_fio, bool loading)
220 {
221         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
222                 return false;
223         }
224         if(!state_fio->StateCheckInt32(this_device_id)) {
225                 return false;
226         }
227         state_fio->StateUint8(ctrl_reg);
228         state_fio->StateUint8(intm_reg);
229         state_fio->StateBool(phase_status);
230         state_fio->StateBool(eop_status);
231         return true;
232 }