OSDN Git Service

817f38452baf83371302fc8fb9750b7b9cbb80d5
[csp-qt/common_source_project-fm7.git] / source / src / vm / scsi_host.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2016.03.01-
6
7         [ SCSI base initiator ]
8 */
9
10 #include "scsi_host.h"
11
12 void SCSI_HOST::reset()
13 {
14         data_reg = 0;
15         bsy_status = cd_status = io_status = msg_status = req_status = 0;
16         access = false;
17         
18         set_irq(false);
19         set_drq(false);
20 }
21
22 #ifdef SCSI_HOST_WIDE
23 void SCSI_HOST::write_dma_io16(uint32_t addr, uint32_t data)
24 #else
25 void SCSI_HOST::write_dma_io8(uint32_t addr, uint32_t data)
26 #endif
27 {
28         #ifdef _SCSI_DEBUG_LOG
29                 emu->force_out_debug_log(_T("[SCSI_HOST] Write %02X\n"), data);
30         #endif
31         write_signals(&outputs_dat, data);
32         
33         #ifdef SCSI_HOST_AUTO_ACK
34                 // set ack to clear req signal immediately
35                 if(bsy_status && !io_status) {
36                         this->write_signal(SIG_SCSI_ACK, 1, 1);
37                 }
38         #endif
39 }
40
41 #ifdef SCSI_HOST_WIDE
42 uint32_t SCSI_HOST::read_dma_io16(uint32_t addr)
43 #else
44 uint32_t SCSI_HOST::read_dma_io8(uint32_t addr)
45 #endif
46 {
47         uint32_t value = data_reg;
48         #ifdef _SCSI_DEBUG_LOG
49                 emu->force_out_debug_log(_T("[SCSI_HOST] Read %02X\n"), value);
50         #endif
51         #ifdef SCSI_HOST_AUTO_ACK
52                 // set ack to clear req signal immediately
53                 if(bsy_status && io_status) {
54                         this->write_signal(SIG_SCSI_ACK, 1, 1);
55                 }
56         #endif
57         return value;
58 }
59
60 void SCSI_HOST::write_signal(int id, uint32_t data, uint32_t mask)
61 {
62         switch(id) {
63         // from initiator
64         case SIG_SCSI_SEL:
65                 #ifdef _SCSI_DEBUG_LOG
66                         emu->out_debug_log(_T("[SCSI_HOST] SEL = %d\n"), (data & mask) ? 1 : 0);
67                 #endif
68                 write_signals(&outputs_sel, (data & mask) ? 0xffffffff : 0);
69                 break;
70                 
71         case SIG_SCSI_ATN:
72                 #ifdef _SCSI_DEBUG_LOG
73 //                      emu->out_debug_log(_T("[SCSI_HOST] ATN = %d\n"), (data & mask) ? 1 : 0);
74                 #endif
75                 write_signals(&outputs_atn, (data & mask) ? 0xffffffff : 0);
76                 break;
77                 
78         case SIG_SCSI_ACK:
79                 #ifdef _SCSI_DEBUG_LOG
80                         emu->out_debug_log(_T("[SCSI_HOST] ACK = %d\n"), (data & mask) ? 1 : 0);
81                 #endif
82                 write_signals(&outputs_ack, (data & mask) ? 0xffffffff : 0);
83                 break;
84                 
85         case SIG_SCSI_RST:
86                 #ifdef _SCSI_DEBUG_LOG
87                         emu->out_debug_log(_T("[SCSI_HOST] RST = %d\n"), (data & mask) ? 1 : 0);
88                 #endif
89                 write_signals(&outputs_rst, (data & mask) ? 0xffffffff : 0);
90                 break;
91                 
92         // from target
93         case SIG_SCSI_DAT:
94                 data_reg &= ~mask;
95                 data_reg |= (data & mask);
96                 break;
97                 
98         case SIG_SCSI_BSY:
99                 bsy_status &= ~mask;
100                 bsy_status |= (data & mask);
101                 write_signals(&outputs_bsy, bsy_status ? 0xffffffff : 0);
102                 break;
103                 
104         case SIG_SCSI_CD:
105                 cd_status &= ~mask;
106                 cd_status |= (data & mask);
107                 break;
108                 
109         case SIG_SCSI_IO:
110                 io_status &= ~mask;
111                 io_status |= (data & mask);
112                 break;
113                 
114         case SIG_SCSI_MSG:
115                 msg_status &= ~mask;
116                 msg_status |= (data & mask);
117                 break;
118                 
119         case SIG_SCSI_REQ:
120                 {
121                         uint32_t prev_status = req_status;
122                         req_status &= ~mask;
123                         req_status |= (data & mask);
124                         
125                         if(!prev_status && req_status) {
126                                 // L -> H
127 //                              if(bsy_status) {
128                                         if(!cd_status && !msg_status) {
129                                                 // data phase
130                                                 set_drq(true);
131                                                 access = true;
132                                         } else if (cd_status) {
133                                                 // command/status/message phase
134                                                 set_irq(true);
135                                         }
136 //                              }
137                         } else if(prev_status && !req_status) {
138                                 // H -> L
139                                 set_drq(false);
140                                 set_irq(false);
141                                 #ifdef SCSI_HOST_AUTO_ACK
142                                         this->write_signal(SIG_SCSI_ACK, 0, 0);
143                                 #endif
144                         }
145                 }
146                 break;
147         }
148 }
149
150 uint32_t SCSI_HOST::read_signal(int id)
151 {
152         // SCSI signals
153         switch (id) {
154         case SIG_SCSI_BSY:
155                 return bsy_status ? 0xffffffff : 0;
156                 
157         case SIG_SCSI_CD:
158                 return cd_status  ? 0xffffffff : 0;
159                 
160         case SIG_SCSI_IO:
161                 return io_status  ? 0xffffffff : 0;
162                 
163         case SIG_SCSI_MSG:
164                 return msg_status ? 0xffffffff : 0;
165                 
166         case SIG_SCSI_REQ:
167                 return req_status ? 0xffffffff : 0;
168         }
169         
170         // access lamp
171         uint32_t value = access ? 0xffffffff : 0;
172         access = false;
173         return value;
174 }
175
176 void SCSI_HOST::set_irq(bool value)
177 {
178         write_signals(&outputs_irq, value ? 0xffffffff : 0);
179 }
180
181 void SCSI_HOST::set_drq(bool value)
182 {
183         write_signals(&outputs_drq, value ? 0xffffffff : 0);
184 }
185
186 #define STATE_VERSION   1
187
188 void SCSI_HOST::save_state(FILEIO* state_fio)
189 {
190         state_fio->FputUint32(STATE_VERSION);
191         state_fio->FputInt32(this_device_id);
192         
193         state_fio->FputUint32(data_reg);
194         state_fio->FputUint32(bsy_status);
195         state_fio->FputUint32(cd_status);
196         state_fio->FputUint32(io_status);
197         state_fio->FputUint32(msg_status);
198         state_fio->FputUint32(req_status);
199 }
200
201 bool SCSI_HOST::load_state(FILEIO* state_fio)
202 {
203         if(state_fio->FgetUint32() != STATE_VERSION) {
204                 return false;
205         }
206         if(state_fio->FgetInt32() != this_device_id) {
207                 return false;
208         }
209         data_reg = state_fio->FgetUint32();
210         bsy_status = state_fio->FgetUint32();
211         cd_status  = state_fio->FgetUint32();
212         io_status  = state_fio->FgetUint32();
213         msg_status = state_fio->FgetUint32();
214         req_status = state_fio->FgetUint32();
215         return true;
216 }
217