2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ SCSI/SASI hard disk drive ]
14 void SCSI_HDD::release()
16 for(int i = 0; i < 8; i++) {
25 void SCSI_HDD::reset()
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]);
41 void SCSI_HDD::open(int drv, const _TCHAR* file_path, int default_sector_size)
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;
48 disk[drv]->open(file_path, default_sector_size);
53 void SCSI_HDD::close(int drv)
55 if(drv < 8 && disk[drv] != NULL) {
56 if(!is_hot_swappable) {
57 image_path[drv][0] = _T('\0');
64 bool SCSI_HDD::mounted(int drv)
66 if(drv < 8 && disk[drv] != NULL) {
67 if(!is_hot_swappable) {
68 return (image_path[drv][0] != _T('\0'));
70 return disk[drv]->mounted();
76 bool SCSI_HDD::accessed(int drv)
78 if(drv < 8 && disk[drv] != NULL) {
79 return disk[drv]->accessed();
84 bool SCSI_HDD::is_device_existing()
86 for(int i = 0; i < 8; i++) {
87 if(disk[i] != NULL && disk[i]->mounted()) {
94 uint32_t SCSI_HDD::physical_block_size()
96 HARDDISK *unit = disk[get_logical_unit_number()];
98 if(unit != NULL && unit->mounted()) {
99 return unit->sector_size;
104 uint32_t SCSI_HDD::logical_block_size()
106 HARDDISK *unit = disk[get_logical_unit_number()];
108 if(unit != NULL && unit->mounted()) {
109 return unit->sector_size;
114 uint32_t SCSI_HDD::max_logical_block_addr()
116 HARDDISK *unit = disk[get_logical_unit_number()];
118 if(unit != NULL && unit->mounted() && unit->sector_num > 0) {
119 return unit->sector_num - 1;
124 bool SCSI_HDD::read_buffer(int length)
126 HARDDISK *unit = disk[get_logical_unit_number()];
128 if(!(unit != NULL && unit->mounted())) {
129 set_sense_code(SCSI_SENSE_NOTREADY);
133 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
134 int tmp_length = min(length, (int)sizeof(tmp_buffer));
136 if(!unit->read_buffer((long)position, tmp_length, tmp_buffer)) {
137 set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
140 for(int i = 0; i < tmp_length; i++) {
141 buffer->write(tmp_buffer[i]);
143 length -= tmp_length;
144 position += tmp_length;
146 set_sense_code(SCSI_SENSE_NOSENSE);
150 bool SCSI_HDD::write_buffer(int length)
152 HARDDISK *unit = disk[get_logical_unit_number()];
154 if(!(unit != NULL && unit->mounted())) {
155 set_sense_code(SCSI_SENSE_NOTREADY);
159 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
160 int tmp_length = min(length, (int)sizeof(tmp_buffer));
162 for(int i = 0; i < tmp_length; i++) {
163 tmp_buffer[i] = buffer->read();
165 if(!unit->write_buffer((long)position, tmp_length, tmp_buffer)) {
166 set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
169 length -= tmp_length;
170 position += tmp_length;
172 set_sense_code(SCSI_SENSE_NOSENSE);
176 #define STATE_VERSION 3
178 bool SCSI_HDD::process_state(FILEIO* state_fio, bool loading)
180 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
183 if(!state_fio->StateCheckInt32(this_device_id)) {
187 for(int drv = 0; drv < 8; drv++) {
188 if(disk[drv] != NULL) {
189 if(!disk[drv]->process_state(state_fio, loading)) {
195 state_fio->StateArray(&image_path[0][0], sizeof(image_path), 1);
196 state_fio->StateArray(sector_size, sizeof(sector_size), 1);
197 return SCSI_DEV::process_state(state_fio, loading);
200 // SASI hard disk drive
202 void SASI_HDD::start_command()
205 case SCSI_CMD_REQ_SENSE:
206 #ifdef _SCSI_DEBUG_LOG
207 this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: Request Sense\n"), scsi_id);
210 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
211 position *= physical_block_size();
214 // create sense data table
216 buffer->write(get_sense_code());
217 buffer->write(((max_logical_block_addr() >> 16) & 0x1f) | (get_logical_unit_number() << 5));
218 buffer->write(((max_logical_block_addr() >> 8) & 0xff));
219 buffer->write(((max_logical_block_addr() >> 0) & 0xff));
220 // change to data in phase
221 set_dat(buffer->read());
222 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
223 set_sense_code(SCSI_SENSE_NOSENSE);
227 #ifdef _SCSI_DEBUG_LOG
228 this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: SASI Command 0xC2\n"), scsi_id);
231 remain = 10; // DTC
\8cn (
\83g
\83\89\83\93\83W
\83X
\83^
\8bZ
\8fpSPECIAL No.27, P.88)
234 // change to data in phase
235 set_phase_delay(SCSI_PHASE_DATA_OUT, 1.0);
238 // start standard command
239 SCSI_HDD::start_command();