OSDN Git Service

8c6632d2a99501ca6caca6b113f1578ef48e46d4
[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 = ack_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                 this->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                 this->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                         this->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 //                      this->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                         this->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                 ack_status = data & mask;
84                 break;
85                 
86         case SIG_SCSI_RST:
87                 #ifdef _SCSI_DEBUG_LOG
88                         this->out_debug_log(_T("[SCSI_HOST] RST = %d\n"), (data & mask) ? 1 : 0);
89                 #endif
90                 write_signals(&outputs_rst, (data & mask) ? 0xffffffff : 0);
91                 break;
92                 
93         // from target
94         case SIG_SCSI_DAT:
95                 data_reg &= ~mask;
96                 data_reg |= (data & mask);
97                 break;
98                 
99         case SIG_SCSI_BSY:
100                 bsy_status &= ~mask;
101                 bsy_status |= (data & mask);
102                 write_signals(&outputs_bsy, bsy_status ? 0xffffffff : 0);
103                 break;
104                 
105         case SIG_SCSI_CD:
106                 cd_status &= ~mask;
107                 cd_status |= (data & mask);
108                 write_signals(&outputs_cd, cd_status ? 0xffffffff : 0);
109                 break;
110                 
111         case SIG_SCSI_IO:
112                 io_status &= ~mask;
113                 io_status |= (data & mask);
114                 write_signals(&outputs_io, io_status ? 0xffffffff : 0);
115                 break;
116                 
117         case SIG_SCSI_MSG:
118                 msg_status &= ~mask;
119                 msg_status |= (data & mask);
120                 write_signals(&outputs_msg, msg_status ? 0xffffffff : 0);
121                 break;
122                 
123         case SIG_SCSI_REQ:
124                 {
125                         uint32_t prev_status = req_status;
126                         req_status &= ~mask;
127                         req_status |= (data & mask);
128                         
129                         if(!prev_status && req_status) {
130                                 // L -> H
131 //                              if(bsy_status) {
132                                         if(!cd_status) {
133                                                 // data phase
134                                                 set_drq(true);
135                                                 access = true;
136                                         } else if(!msg_status && io_status) {
137                                                 // status phase
138                                                 set_irq(true);
139                                         }
140 //                              }
141                         } else if(prev_status && !req_status) {
142                                 // H -> L
143                                 set_drq(false);
144                                 set_irq(false);
145                                 #ifdef SCSI_HOST_AUTO_ACK
146                                         this->write_signal(SIG_SCSI_ACK, 0, 0);
147                                 #endif
148                         }
149                         write_signals(&outputs_req, req_status ? 0xffffffff : 0);
150                 }
151                 break;
152         }
153 }
154
155 uint32_t SCSI_HOST::read_signal(int id)
156 {
157         // SCSI signals
158         switch (id) {
159         case SIG_SCSI_BSY:
160                 return bsy_status ? 0xffffffff : 0;
161                 
162         case SIG_SCSI_CD:
163                 return cd_status  ? 0xffffffff : 0;
164                 
165         case SIG_SCSI_IO:
166                 return io_status  ? 0xffffffff : 0;
167                 
168         case SIG_SCSI_MSG:
169                 return msg_status ? 0xffffffff : 0;
170                 
171         case SIG_SCSI_REQ:
172                 return req_status ? 0xffffffff : 0;
173                 
174         case SIG_SCSI_ACK:
175                 return ack_status ? 0xffffffff : 0;
176         }
177         
178         // access lamp
179         uint32_t value = access ? 0xffffffff : 0;
180         access = false;
181         return value;
182 }
183
184 void SCSI_HOST::set_irq(bool value)
185 {
186         write_signals(&outputs_irq, value ? 0xffffffff : 0);
187 }
188
189 void SCSI_HOST::set_drq(bool value)
190 {
191         write_signals(&outputs_drq, value ? 0xffffffff : 0);
192 }
193
194 #define STATE_VERSION   2
195
196 bool SCSI_HOST::process_state(FILEIO* state_fio, bool loading)
197 {
198         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
199                 return false;
200         }
201         if(!state_fio->StateCheckInt32(this_device_id)) {
202                 return false;
203         }
204         state_fio->StateValue(data_reg);
205         state_fio->StateValue(bsy_status);
206         state_fio->StateValue(cd_status);
207         state_fio->StateValue(io_status);
208         state_fio->StateValue(msg_status);
209         state_fio->StateValue(req_status);
210         state_fio->StateValue(ack_status);
211         return true;
212 }
213