OSDN Git Service

[VM][WIP] Apply some devices merging upstream 2018-10-05.This still not build.WIP.
[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                 break;
109                 
110         case SIG_SCSI_IO:
111                 io_status &= ~mask;
112                 io_status |= (data & mask);
113                 break;
114                 
115         case SIG_SCSI_MSG:
116                 msg_status &= ~mask;
117                 msg_status |= (data & mask);
118                 break;
119                 
120         case SIG_SCSI_REQ:
121                 {
122                         uint32_t prev_status = req_status;
123                         req_status &= ~mask;
124                         req_status |= (data & mask);
125                         
126                         if(!prev_status && req_status) {
127                                 // L -> H
128 //                              if(bsy_status) {
129                                         if(!cd_status && !msg_status) {
130                                                 // data phase
131                                                 set_drq(true);
132                                                 access = true;
133                                         } else if (cd_status) {
134                                                 // command/status/message phase
135                                                 set_irq(true);
136                                         }
137 //                              }
138                         } else if(prev_status && !req_status) {
139                                 // H -> L
140                                 set_drq(false);
141                                 set_irq(false);
142                                 #ifdef SCSI_HOST_AUTO_ACK
143                                         this->write_signal(SIG_SCSI_ACK, 0, 0);
144                                 #endif
145                         }
146                 }
147                 break;
148         }
149 }
150
151 uint32_t SCSI_HOST::read_signal(int id)
152 {
153         // SCSI signals
154         switch (id) {
155         case SIG_SCSI_BSY:
156                 return bsy_status ? 0xffffffff : 0;
157                 
158         case SIG_SCSI_CD:
159                 return cd_status  ? 0xffffffff : 0;
160                 
161         case SIG_SCSI_IO:
162                 return io_status  ? 0xffffffff : 0;
163                 
164         case SIG_SCSI_MSG:
165                 return msg_status ? 0xffffffff : 0;
166                 
167         case SIG_SCSI_REQ:
168                 return req_status ? 0xffffffff : 0;
169                 
170         case SIG_SCSI_ACK:
171                 return ack_status ? 0xffffffff : 0;
172         }
173         
174         // access lamp
175         uint32_t value = access ? 0xffffffff : 0;
176         access = false;
177         return value;
178 }
179
180 void SCSI_HOST::set_irq(bool value)
181 {
182         write_signals(&outputs_irq, value ? 0xffffffff : 0);
183 }
184
185 void SCSI_HOST::set_drq(bool value)
186 {
187         write_signals(&outputs_drq, value ? 0xffffffff : 0);
188 }
189
190 #define STATE_VERSION   2
191
192 bool SCSI_HOST::process_state(FILEIO* state_fio, bool loading)
193 {
194         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
195                 return false;
196         }
197         if(!state_fio->StateCheckInt32(this_device_id)) {
198                 return false;
199         }
200         state_fio->StateUint32(data_reg);
201         state_fio->StateUint32(bsy_status);
202         state_fio->StateUint32(cd_status);
203         state_fio->StateUint32(io_status);
204         state_fio->StateUint32(msg_status);
205         state_fio->StateUint32(req_status);
206         state_fio->StateUint32(ack_status);
207         return true;
208 }
209