OSDN Git Service

[General][Qt] Merge updtream 2016-03-05 (1).FTBFSs exist yet.
[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 = false;
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                 if(bsy_status && !io_status) {
35                         this->write_signal(SIG_SCSI_ACK, 1, 1);
36                 }
37         #endif
38 }
39
40 #ifdef SCSI_HOST_WIDE
41 uint32_t SCSI_HOST::read_dma_io16(uint32_t addr)
42 #else
43 uint32_t SCSI_HOST::read_dma_io8(uint32_t addr)
44 #endif
45 {
46         uint32_t value = data_reg;
47         #ifdef _SCSI_DEBUG_LOG
48                 emu->force_out_debug_log(_T("[SCSI_HOST] Read %02X\n"), value);
49         #endif
50         #ifdef SCSI_HOST_AUTO_ACK
51                 if(bsy_status && io_status) {
52                         this->write_signal(SIG_SCSI_ACK, 1, 1);
53                 }
54         #endif
55         return value;
56 }
57
58 void SCSI_HOST::write_signal(int id, uint32_t data, uint32_t mask)
59 {
60         switch(id) {
61         // from initiator
62         case SIG_SCSI_SEL:
63                 write_signals(&outputs_sel, (data & mask) ? 0xffffffff : 0);
64                 break;
65                 
66         case SIG_SCSI_ATN:
67                 write_signals(&outputs_atn, (data & mask) ? 0xffffffff : 0);
68                 break;
69                 
70         case SIG_SCSI_ACK:
71                 write_signals(&outputs_ack, (data & mask) ? 0xffffffff : 0);
72                 break;
73                 
74         case SIG_SCSI_RST:
75                 write_signals(&outputs_rst, (data & mask) ? 0xffffffff : 0);
76                 break;
77                 
78         // from target
79         case SIG_SCSI_DAT:
80                 data_reg &= ~mask;
81                 data_reg |= (data & mask);
82                 break;
83                 
84         case SIG_SCSI_BSY:
85                 bsy_status &= ~mask;
86                 bsy_status |= (data & mask);
87                 break;
88                 
89         case SIG_SCSI_CD:
90                 cd_status &= ~mask;
91                 cd_status |= (data & mask);
92                 break;
93                 
94         case SIG_SCSI_IO:
95                 io_status &= ~mask;
96                 io_status |= (data & mask);
97                 break;
98                 
99         case SIG_SCSI_MSG:
100                 msg_status &= ~mask;
101                 msg_status |= (data & mask);
102                 break;
103                 
104         case SIG_SCSI_REQ:
105                 {
106                         uint32_t prev_status = req_status;
107                         req_status &= ~mask;
108                         req_status |= (data & mask);
109                         
110                         if(!prev_status && req_status) {
111                                 // L -> H
112 //                              if(bsy_status) {
113                                         if(!cd_status && !msg_status) {
114                                                 // data phase
115                                                 set_drq(true);
116                                                 access = true;
117                                         }
118                                         else if (cd_status) {
119                                                 // command/status/message phase
120                                                 set_irq(true);
121                                         }
122 //                              }
123                         } else if(prev_status && !req_status) {
124                                 // H -> L
125                                 set_drq(false);
126                                 set_irq(false);
127                                 #ifdef SCSI_HOST_AUTO_ACK
128                                         this->write_signal(SIG_SCSI_ACK, 0, 0);
129                                 #endif
130                         }
131                 }
132                 break;
133         }
134 }
135
136 uint32_t SCSI_HOST::read_signal(int id)
137 {
138         // SCSI signals
139         switch (id) {
140         case SIG_SCSI_BSY:
141                 return bsy_status ? 0xffffffff : 0;
142                 
143         case SIG_SCSI_CD:
144                 return cd_status  ? 0xffffffff : 0;
145                 
146         case SIG_SCSI_IO:
147                 return io_status  ? 0xffffffff : 0;
148                 
149         case SIG_SCSI_MSG:
150                 return msg_status ? 0xffffffff : 0;
151                 
152         case SIG_SCSI_REQ:
153                 return req_status ? 0xffffffff : 0;
154         }
155         
156         // access lamp
157         uint32_t value = access ? 0xffffffff : 0;
158         access = false;
159         return value;
160 }
161
162 void SCSI_HOST::set_irq(bool value)
163 {
164         write_signals(&outputs_irq, value ? 0xffffffff : 0);
165 }
166
167 void SCSI_HOST::set_drq(bool value)
168 {
169         write_signals(&outputs_drq, value ? 0xffffffff : 0);
170 }
171
172 #define STATE_VERSION   1
173
174 void SCSI_HOST::save_state(FILEIO* state_fio)
175 {
176         state_fio->FputUint32(STATE_VERSION);
177         state_fio->FputInt32(this_device_id);
178         
179         state_fio->FputUint32(data_reg);
180         state_fio->FputUint32(bsy_status);
181         state_fio->FputUint32(cd_status);
182         state_fio->FputUint32(io_status);
183         state_fio->FputUint32(msg_status);
184         state_fio->FputUint32(req_status);
185 }
186
187 bool SCSI_HOST::load_state(FILEIO* state_fio)
188 {
189         if(state_fio->FgetUint32() != STATE_VERSION) {
190                 return false;
191         }
192         if(state_fio->FgetInt32() != this_device_id) {
193                 return false;
194         }
195         data_reg = state_fio->FgetUint32();
196         bsy_status = state_fio->FgetUint32();
197         cd_status  = state_fio->FgetUint32();
198         io_status  = state_fio->FgetUint32();
199         msg_status = state_fio->FgetUint32();
200         req_status = state_fio->FgetUint32();
201         return true;
202 }
203