OSDN Git Service

[General] Merge Upstream 2018-12-18.
[csp-qt/common_source_project-fm7.git] / source / src / vm / scsi_hdd.cpp
index 955c3a3..faf03bd 100644 (file)
@@ -4,7 +4,7 @@
        Author : Takeda.Toshiya
        Date   : 2016.03.01-
 
-       [ SCSI hard disk drive ]
+       [ SCSI/SASI hard disk drive ]
 */
 
 #include "scsi_hdd.h"
@@ -22,6 +22,65 @@ void SCSI_HDD::release()
        SCSI_DEV::release();
 }
 
+void SCSI_HDD::reset()
+{
+       if(!is_hot_swappable) {
+               for(int drv = 0; drv < 8; drv++) {
+                       if(disk[drv] != NULL) {
+                               if(image_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(image_path[drv])) {
+                                       disk[drv]->open(image_path[drv], sector_size[drv]);
+                               } else {
+                                       disk[drv]->close();
+                               }
+                       }
+               }
+       }
+       SCSI_DEV::reset();
+}
+
+void SCSI_HDD::open(int drv, const _TCHAR* file_path, int default_sector_size)
+{
+       if(drv < 8 && disk[drv] != NULL) {
+               if(!is_hot_swappable) {
+                       my_tcscpy_s(image_path[drv], _MAX_PATH, file_path);
+                       sector_size[drv] = default_sector_size;
+               } else {
+                       disk[drv]->open(file_path, default_sector_size);
+               }
+       }
+}
+
+void SCSI_HDD::close(int drv)
+{
+       if(drv < 8 && disk[drv] != NULL) {
+               if(!is_hot_swappable) {
+                       image_path[drv][0] = _T('\0');
+               } else {
+                       disk[drv]->close();
+               }
+       }
+}
+
+bool SCSI_HDD::mounted(int drv)
+{
+       if(drv < 8 && disk[drv] != NULL) {
+               if(!is_hot_swappable) {
+                       return (image_path[drv][0] != _T('\0'));
+               } else {
+                       return disk[drv]->mounted();
+               }
+       }
+       return false;
+}
+
+bool SCSI_HDD::accessed(int drv)
+{
+       if(drv < 8 && disk[drv] != NULL) {
+               return disk[drv]->accessed();
+       }
+       return false;
+}
+
 bool SCSI_HDD::is_device_existing()
 {
        for(int i = 0; i < 8; i++) {
@@ -39,7 +98,7 @@ uint32_t SCSI_HDD::physical_block_size()
        if(unit != NULL && unit->mounted()) {
                return unit->sector_size;
        }
-       return 512;
+       return 0;// 512;
 }
 
 uint32_t SCSI_HDD::logical_block_size()
@@ -49,101 +108,149 @@ uint32_t SCSI_HDD::logical_block_size()
        if(unit != NULL && unit->mounted()) {
                return unit->sector_size;
        }
-       return 512;
+       return 0;// 512;
 }
 
 uint32_t SCSI_HDD::max_logical_block_addr()
 {
        HARDDISK *unit = disk[get_logical_unit_number()];
        
-       if(unit != NULL && unit->mounted()) {
-               return unit->cylinders * unit->surfaces * unit->sectors;
+       if(unit != NULL && unit->mounted() && unit->sector_num > 0) {
+               return unit->sector_num - 1;
        }
        return 0;
 }
 
-void SCSI_HDD::read_buffer(int length)
+bool SCSI_HDD::read_buffer(int length)
 {
+       if(!(command[0] == SCSI_CMD_READ6 || command[0] == SCSI_CMD_READ10 || command[0] == SCSI_CMD_READ12)) {
+               for(int i = 0; i < length; i++) {
+                       buffer->write(0);
+                       position++;
+               }
+               set_sense_code(SCSI_SENSE_NOSENSE);
+               return true;
+       }
        HARDDISK *unit = disk[get_logical_unit_number()];
        
-       if(unit != NULL && unit->mounted()) {
-               while(length > 0) {
-                       uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
-                       int tmp_length = min(length, (int)sizeof(tmp_buffer));
-                       
-                       unit->read_buffer((long)position, tmp_length, tmp_buffer);
-                       for(int i = 0; i < tmp_length; i++) {
-                               buffer->write(tmp_buffer[i]);
-                       }
-                       length -= tmp_length;
-                       position += tmp_length;
-               }
+       if(!(unit != NULL && unit->mounted())) {
+               set_sense_code(SCSI_SENSE_NOTREADY);
+               return false;
        }
+       while(length > 0) {
+               uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
+               int tmp_length = min(length, (int)sizeof(tmp_buffer));
+               
+               if(!unit->read_buffer((long)position, tmp_length, tmp_buffer)) {
+                       set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
+                       return false;
+               }
+               for(int i = 0; i < tmp_length; i++) {
+                       buffer->write(tmp_buffer[i]);
+               }
+               length -= tmp_length;
+               position += tmp_length;
+       }
+       set_sense_code(SCSI_SENSE_NOSENSE);
+       return true;
 }
 
-void SCSI_HDD::write_buffer(int length)
+bool SCSI_HDD::write_buffer(int length)
 {
+       if(!(command[0] == SCSI_CMD_WRITE6 || command[0] == SCSI_CMD_WRITE10 || command[0] == SCSI_CMD_WRITE12)) {
+               for(int i = 0; i < length; i++) {
+                       buffer->read();
+                       position++;
+               }
+               set_sense_code(SCSI_SENSE_NOSENSE);
+               return true;
+       }
        HARDDISK *unit = disk[get_logical_unit_number()];
        
-       if(unit != NULL && unit->mounted()) {
-               while(length > 0) {
-                       uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
-                       int tmp_length = min(length, (int)sizeof(tmp_buffer));
-                       
-                       for(int i = 0; i < tmp_length; i++) {
-                               tmp_buffer[i] = buffer->read();
-                       }
-                       unit->write_buffer((long)position, tmp_length, tmp_buffer);
-                       length -= tmp_length;
-                       position += tmp_length;
-               }
+       if(!(unit != NULL && unit->mounted())) {
+               set_sense_code(SCSI_SENSE_NOTREADY);
+               return false;
        }
+       while(length > 0) {
+               uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
+               int tmp_length = min(length, (int)sizeof(tmp_buffer));
+               
+               for(int i = 0; i < tmp_length; i++) {
+                       tmp_buffer[i] = buffer->read();
+               }
+               if(!unit->write_buffer((long)position, tmp_length, tmp_buffer)) {
+                       set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
+                       return false;
+               }
+               length -= tmp_length;
+               position += tmp_length;
+       }
+       set_sense_code(SCSI_SENSE_NOSENSE);
+       return true;
 }
 
-#define STATE_VERSION  1
-
-#include "../statesub.h"
+#define STATE_VERSION  3
 
-void SCSI_HDD::decl_state()
+bool SCSI_HDD::process_state(FILEIO* state_fio, bool loading)
 {
-       enter_decl_state(STATE_VERSION);
-       
-       SCSI_DEV::decl_state();
-
-       leave_decl_state();
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       /*
+       for(int drv = 0; drv < 8; drv++) {
+               if(disk[drv] != NULL) {
+                       if(!disk[drv]->process_state(state_fio, loading)) {
+                               return false;
+                       }
+               }
+       }
+       */
+       state_fio->StateArray(&image_path[0][0], sizeof(image_path), 1);
+       state_fio->StateArray(sector_size, sizeof(sector_size), 1);
+       return SCSI_DEV::process_state(state_fio, loading);
 }
 
-void SCSI_HDD::save_state(FILEIO* state_fio)
-{
-//     state_fio->FputUint32(STATE_VERSION);
-//     state_fio->FputInt32(this_device_id);
-/*
-       for(int i = 0; i < 8; i++) {
-               if(disk[i] != NULL) {
-                       disk[i]->save_state(state_fio);
-               }
-       }
-*/
-       SCSI_DEV::save_state(state_fio);
-}
+// SASI hard disk drive
 
-bool SCSI_HDD::load_state(FILEIO* state_fio)
+void SASI_HDD::start_command()
 {
-//     if(state_fio->FgetUint32() != STATE_VERSION) {
-//             return false;
-//     }
-//     if(state_fio->FgetInt32() != this_device_id) {
-//             return false;
-//     }
-/*
-       for(int i = 0; i < 8; i++) {
-               if(disk[i] != NULL) {
-                       if(!disk[i]->load_state(state_fio)) {
-                               return false;
-                       }
-               }
+       switch(command[0]) {
+       case SCSI_CMD_REQ_SENSE:
+               #ifdef _SCSI_DEBUG_LOG
+                       this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: Request Sense\n"), scsi_id);
+               #endif
+               // start position
+               position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
+               position *= physical_block_size();
+               // transfer length
+               remain = 4;
+               // create sense data table
+               buffer->clear();
+               buffer->write(get_sense_code());
+               buffer->write(((max_logical_block_addr() >> 16) & 0x1f) | (get_logical_unit_number() << 5));
+               buffer->write(((max_logical_block_addr() >>  8) & 0xff));
+               buffer->write(((max_logical_block_addr() >>  0) & 0xff));
+               // change to data in phase
+               set_dat(buffer->read());
+               set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
+               set_sense_code(SCSI_SENSE_NOSENSE);
+               return;
+               
+       case 0xc2:
+               #ifdef _SCSI_DEBUG_LOG
+                       this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: SASI Command 0xC2\n"), scsi_id);
+               #endif
+               // transfer length
+               remain = 10; // DTC\8cn (\83g\83\89\83\93\83W\83X\83^\8bZ\8fpSPECIAL No.27, P.88)
+               // clear data buffer
+               buffer->clear();
+               // change to data in phase
+               set_phase_delay(SCSI_PHASE_DATA_OUT, 1.0);
+               return;
        }
-*/
-       return SCSI_DEV::load_state(state_fio);
+       // start standard command
+       SCSI_HDD::start_command();
 }
-