X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=source%2Fsrc%2Fvm%2Fscsi_hdd.cpp;h=faf03bd3d426c73a31c4a0c61493112c41f388cc;hb=89a913067210d1169704559b0a56b35cc9381c4f;hp=43cbcdf4661e45a0732bd30345cf90b71723c942;hpb=690cac2c36ad20d27515ed90b5bd241a685b8dc1;p=csp-qt%2Fcommon_source_project-fm7.git diff --git a/source/src/vm/scsi_hdd.cpp b/source/src/vm/scsi_hdd.cpp index 43cbcdf46..faf03bd3d 100644 --- a/source/src/vm/scsi_hdd.cpp +++ b/source/src/vm/scsi_hdd.cpp @@ -4,175 +4,253 @@ Author : Takeda.Toshiya Date : 2016.03.01- - [ SCSI hard disk drive ] + [ SCSI/SASI hard disk drive ] */ #include "scsi_hdd.h" +#include "harddisk.h" #include "../fifo.h" -void SCSI_HDD::initialize_max_logical_block_addr() +void SCSI_HDD::release() { - if(max_logical_block_addr == 0) { - FILEIO* fio = new FILEIO(); - uint32_t file_size = 0; - - if(default_drive_size == 0) { - default_drive_size = 0x2800000; // 40MB + for(int i = 0; i < 8; i++) { + if(disk[i] != NULL) { + disk[i]->close(); + delete disk[i]; } - if(FILEIO::IsFileExisting(create_local_path(_T("SCSI%d.DAT"), scsi_id))) { - if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_WRITE_BINARY)) { - if((file_size = fio->FileLength()) == 0) { - uint32_t remain = (file_size = default_drive_size); - void *tmp = calloc(1, SCSI_BUFFER_SIZE); - while(remain > 0) { - uint32_t length = min(remain, (uint32_t)SCSI_BUFFER_SIZE); - fio->Fwrite(tmp, length, 1); - remain -= length; - } - free(tmp); + } + 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(); } - fio->Fclose(); } + } + } + 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 { - if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_WRITE_BINARY)) { - uint32_t remain = (file_size = default_drive_size); - void *tmp = calloc(1, SCSI_BUFFER_SIZE); - while(remain > 0) { - uint32_t length = min(remain, (uint32_t)SCSI_BUFFER_SIZE); - fio->Fwrite(tmp, length, 1); - remain -= length; - } - free(tmp); - fio->Fclose(); - } + 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++) { + if(disk[i] != NULL && disk[i]->mounted()) { + return true; + } + } + return false; +} + +uint32_t SCSI_HDD::physical_block_size() +{ + HARDDISK *unit = disk[get_logical_unit_number()]; + + if(unit != NULL && unit->mounted()) { + return unit->sector_size; + } + return 0;// 512; +} + +uint32_t SCSI_HDD::logical_block_size() +{ + HARDDISK *unit = disk[get_logical_unit_number()]; + + if(unit != NULL && unit->mounted()) { + return unit->sector_size; + } + return 0;// 512; +} + +uint32_t SCSI_HDD::max_logical_block_addr() +{ + HARDDISK *unit = disk[get_logical_unit_number()]; + + if(unit != NULL && unit->mounted() && unit->sector_num > 0) { + return unit->sector_num - 1; + } + return 0; +} + +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())) { + 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; } - if(file_size != 0) { - max_logical_block_addr = (file_size / logical_block_size) - 1; + 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; +} + +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++; } - delete fio; + set_sense_code(SCSI_SENSE_NOSENSE); + return true; + } + HARDDISK *unit = disk[get_logical_unit_number()]; + + 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; } -void SCSI_HDD::start_command() +#define STATE_VERSION 3 + +bool SCSI_HDD::process_state(FILEIO* state_fio, bool loading) +{ + 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); +} + +// SASI hard disk drive + +void SASI_HDD::start_command() { switch(command[0]) { - case SCSI_CMD_INQUIRY: + case SCSI_CMD_REQ_SENSE: #ifdef _SCSI_DEBUG_LOG - emu->out_debug_log(_T("[SCSI_HDD:ID=%d] Command: Inquiry\n"), scsi_id); + 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]) * logical_block_size; + position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]; + position *= physical_block_size(); // transfer length - remain = 32; + remain = 4; // create sense data table buffer->clear(); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x02); // ANSI SCSI2 - buffer->write(0x01); // ANSI-CCS - buffer->write(0x1c); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x18); - for(int i = 0; i < (int)strlen(vendor_id) && i < 8; i++) { - buffer->write(vendor_id[i]); - } - for(int i = strlen(vendor_id); i < 8; i++) { - buffer->write(0x20); - } - for(int i = 0; i < (int)strlen(product_id) && i < 16; i++) { - buffer->write(vendor_id[i]); - } - for(int i = strlen(product_id); i < 16; i++) { - buffer->write(0x20); - } - // set first data - set_dat(buffer->read()); + 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); - break; + set_sense_code(SCSI_SENSE_NOSENSE); + return; - case SCSI_CMD_RD_CAPAC: + case 0xc2: #ifdef _SCSI_DEBUG_LOG - emu->out_debug_log(_T("[SCSI_HDD:ID=%d] Command: Read Capacity\n"), scsi_id); + this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: SASI Command 0xC2\n"), scsi_id); #endif - // initialize max logical block address - initialize_max_logical_block_addr(); - // start position - position = (command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5]) * logical_block_size; // transfer length - remain = 8; - // create capacity data table + remain = 10; // DTCŒn (ƒgƒ‰ƒ“ƒWƒXƒ^‹ZpSPECIAL No.27, P.88) + // clear data buffer buffer->clear(); - buffer->write((max_logical_block_addr >> 24) & 0xff); - buffer->write((max_logical_block_addr >> 16) & 0xff); - buffer->write((max_logical_block_addr >> 8) & 0xff); - buffer->write((max_logical_block_addr >> 0) & 0xff); - buffer->write(( logical_block_size >> 24) & 0xff); - buffer->write(( logical_block_size >> 16) & 0xff); - buffer->write(( logical_block_size >> 8) & 0xff); - buffer->write(( logical_block_size >> 0) & 0xff); - // set first data - set_dat(buffer->read()); // change to data in phase - set_phase_delay(SCSI_PHASE_DATA_IN, 10.0); - break; - - default: - SCSI_DEV::start_command(); - break; - } -} - -void SCSI_HDD::read_buffer(int length) -{ - // make sure drive size is not zero - initialize_max_logical_block_addr(); - - // read blocks - FILEIO* fio = new FILEIO(); - if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_BINARY)) { - // FIXME: consider the case that disk size is bigger than MAX_LONG - fio->Fseek((long)position, FILEIO_SEEK_SET); - while(length > 0) { - uint8_t tmp_buffer[SCSI_BUFFER_SIZE]; - int tmp_length = min(length, sizeof(tmp_buffer)); - - fio->Fread(tmp_buffer, tmp_length, 1); - for(int i = 0; i < tmp_length; i++) { - buffer->write(tmp_buffer[i]); - } - length -= tmp_length; - position += tmp_length; - } - fio->Fclose(); - } - delete fio; -} - -void SCSI_HDD::write_buffer(int length) -{ - // make sure drive size is not zero - initialize_max_logical_block_addr(); - - // write blocks - FILEIO* fio = new FILEIO(); - if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_WRITE_BINARY)) { - // FIXME: consider the case that disk size is bigger than MAX_LONG - fio->Fseek((long)position, FILEIO_SEEK_SET); - while(length > 0) { - uint8_t tmp_buffer[SCSI_BUFFER_SIZE]; - int tmp_length = min(length, sizeof(tmp_buffer)); - - for(int i = 0; i < tmp_length; i++) { - tmp_buffer[i] = buffer->read(); - } - fio->Fwrite(tmp_buffer, tmp_length, 1); - length -= tmp_length; - position += tmp_length; - } - fio->Fclose(); + set_phase_delay(SCSI_PHASE_DATA_OUT, 1.0); + return; } - delete fio; + // start standard command + SCSI_HDD::start_command(); } -