OSDN Git Service

ccfa06142c4028921801b0cab92faa30277d9932
[csp-qt/common_source_project-fm7.git] / source / src / vm / scsi_hdd.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2016.03.01-
6
7         [ SCSI/SASI hard disk drive ]
8 */
9
10 #include "scsi_hdd.h"
11 #include "harddisk.h"
12 #include "../fifo.h"
13
14 void SCSI_HDD::release()
15 {
16         for(int i = 0; i < 8; i++) {
17                 if(disk[i] != NULL) {
18                         disk[i]->close();
19                         delete disk[i];
20                 }
21         }
22         SCSI_DEV::release();
23 }
24
25 void SCSI_HDD::reset()
26 {
27         if(!is_hot_swappable) {
28                 for(int drv = 0; drv < 8; drv++) {
29                         if(disk[drv] != NULL) {
30                                 if(image_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(image_path[drv])) {
31                                         disk[drv]->open(image_path[drv], sector_size[drv]);
32                                 } else {
33                                         disk[drv]->close();
34                                 }
35                         }
36                 }
37         }
38         SCSI_DEV::reset();
39 }
40
41 void SCSI_HDD::open(int drv, const _TCHAR* file_path, int default_sector_size)
42 {
43         if(drv < 8 && disk[drv] != NULL) {
44                 if(!is_hot_swappable) {
45                         my_tcscpy_s(image_path[drv], _MAX_PATH, file_path);
46                         sector_size[drv] = default_sector_size;
47                 } else {
48                         disk[drv]->open(file_path, default_sector_size);
49                 }
50         }
51 }
52
53 void SCSI_HDD::close(int drv)
54 {
55         if(drv < 8 && disk[drv] != NULL) {
56                 if(!is_hot_swappable) {
57                         image_path[drv][0] = _T('\0');
58                 } else {
59                         disk[drv]->close();
60                 }
61         }
62 }
63
64 bool SCSI_HDD::mounted(int drv)
65 {
66         if(drv < 8 && disk[drv] != NULL) {
67                 if(!is_hot_swappable) {
68                         return (image_path[drv][0] != _T('\0'));
69                 } else {
70                         return disk[drv]->mounted();
71                 }
72         }
73         return false;
74 }
75
76 bool SCSI_HDD::accessed(int drv)
77 {
78         if(drv < 8 && disk[drv] != NULL) {
79                 return disk[drv]->accessed();
80         }
81         return false;
82 }
83
84 bool SCSI_HDD::is_device_existing()
85 {
86         for(int i = 0; i < 8; i++) {
87                 if(disk[i] != NULL && disk[i]->mounted()) {
88                         return true;
89                 }
90         }
91         return false;
92 }
93
94 uint32_t SCSI_HDD::physical_block_size()
95 {
96         HARDDISK *unit = disk[get_logical_unit_number()];
97         
98         if(unit != NULL && unit->mounted()) {
99                 return unit->sector_size;
100         }
101         return 0;// 512;
102 }
103
104 uint32_t SCSI_HDD::logical_block_size()
105 {
106         HARDDISK *unit = disk[get_logical_unit_number()];
107         
108         if(unit != NULL && unit->mounted()) {
109                 return unit->sector_size;
110         }
111         return 0;// 512;
112 }
113
114 uint32_t SCSI_HDD::max_logical_block_addr()
115 {
116         HARDDISK *unit = disk[get_logical_unit_number()];
117         
118         if(unit != NULL && unit->mounted() && unit->sector_num > 0) {
119                 return unit->sector_num - 1;
120         }
121         return 0;
122 }
123
124 bool SCSI_HDD::read_buffer(int length)
125 {
126         HARDDISK *unit = disk[get_logical_unit_number()];
127         
128         if(!(unit != NULL && unit->mounted())) {
129                 set_sense_code(SCSI_SENSE_NOTREADY);
130                 return false;
131         }
132         while(length > 0) {
133                 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
134                 int tmp_length = min(length, (int)sizeof(tmp_buffer));
135                 
136                 if(!unit->read_buffer((long)position, tmp_length, tmp_buffer)) {
137                         set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
138                         return false;
139                 }
140                 for(int i = 0; i < tmp_length; i++) {
141                         buffer->write(tmp_buffer[i]);
142                 }
143                 length -= tmp_length;
144                 position += tmp_length;
145         }
146         set_sense_code(SCSI_SENSE_NOSENSE);
147         return true;
148 }
149
150 bool SCSI_HDD::write_buffer(int length)
151 {
152         HARDDISK *unit = disk[get_logical_unit_number()];
153         
154         if(!(unit != NULL && unit->mounted())) {
155                 set_sense_code(SCSI_SENSE_NOTREADY);
156                 return false;
157         }
158         while(length > 0) {
159                 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
160                 int tmp_length = min(length, (int)sizeof(tmp_buffer));
161                 
162                 for(int i = 0; i < tmp_length; i++) {
163                         tmp_buffer[i] = buffer->read();
164                 }
165                 if(!unit->write_buffer((long)position, tmp_length, tmp_buffer)) {
166                         set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
167                         return false;
168                 }
169                 length -= tmp_length;
170                 position += tmp_length;
171         }
172         set_sense_code(SCSI_SENSE_NOSENSE);
173         return true;
174 }
175
176 #define STATE_VERSION   3
177
178 #include "../statesub.h"
179
180 void SCSI_HDD::decl_state()
181 {
182         enter_decl_state(STATE_VERSION);
183
184         for(int i = 0; i < 8; i++) {
185                 DECL_STATE_ENTRY_STRING_MEMBER(&(image_path[i][0]), MAX_PATH, i);
186         }
187         DECL_STATE_ENTRY_1D_ARRAY(sector_size, sizeof(sector_size) / sizeof(int));  
188         leave_decl_state();
189
190         SCSI_DEV::decl_state();
191 }
192
193 void SCSI_HDD::save_state(FILEIO* state_fio)
194 {
195         uint32_t crc_value = 0xffffffff;
196         if(state_entry != NULL) {
197                 state_entry->save_state(state_fio, &crc_value);
198         }
199 //      state_fio->FputUint32(STATE_VERSION);
200 //      state_fio->FputInt32(this_device_id);
201 /*
202         for(int i = 0; i < 8; i++) {
203                 if(disk[i] != NULL) {
204                         disk[i]->save_state(state_fio);
205                 }
206         }
207 */
208 //      SCSI_DEV::save_state(state_fio);
209 }
210
211 bool SCSI_HDD::load_state(FILEIO* state_fio)
212 {
213         uint32_t crc_value = 0xffffffff;
214         bool stat = false;
215         bool mb = false;
216         if(state_entry != NULL) {
217            mb = state_entry->load_state(state_fio, &crc_value);
218         }
219         if(!mb) return false;
220 //      if(state_fio->FgetUint32() != STATE_VERSION) {
221 //              return false;
222 //      }
223 //      if(state_fio->FgetInt32() != this_device_id) {
224 //              return false;
225 //      }
226 /*
227         for(int i = 0; i < 8; i++) {
228                 if(disk[i] != NULL) {
229                         if(!disk[i]->load_state(state_fio)) {
230                                 return false;
231                         }
232                 }
233         }
234 */
235 //      return SCSI_DEV::load_state(state_fio);
236         return true;
237 }
238