From 89a913067210d1169704559b0a56b35cc9381c4f Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Sat, 12 Jan 2019 18:22:09 +0900 Subject: [PATCH] [General] Merge Upstream 2018-12-18. --- source/src/vm/scsi_cdrom.cpp | 59 ++++++++++++++++++++++++++++---- source/src/vm/scsi_dev.cpp | 80 +++++++++++++++++--------------------------- source/src/vm/scsi_hdd.cpp | 16 +++++++++ source/src/vm/scsi_host.cpp | 2 +- 4 files changed, 99 insertions(+), 58 deletions(-) diff --git a/source/src/vm/scsi_cdrom.cpp b/source/src/vm/scsi_cdrom.cpp index 52aab9bdd..6a0510f4f 100644 --- a/source/src/vm/scsi_cdrom.cpp +++ b/source/src/vm/scsi_cdrom.cpp @@ -1,4 +1,4 @@ -/* +k/* Skelton for retropc emulator Author : Takeda.Toshiya @@ -430,8 +430,25 @@ void SCSI_CDROM::start_command() #ifdef _SCSI_DEBUG_LOG this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Read Mode Select 6-byte\n"), scsi_id); #endif - read_mode = (command[4] != 0); - break; + // start position +// position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]; +// position *= physical_block_size(); + position = 0; + // transfer length +// remain = command[4];// * logical_block_size(); + remain = 11; + if(remain != 0) { + // clear data buffer + buffer->clear(); + // change to data in phase + set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time); + } else { + // transfer length is zero, change to status phase + set_dat(SCSI_STATUS_GOOD); + set_sense_code(SCSI_SENSE_NOSENSE); + set_phase_delay(SCSI_PHASE_STATUS, 10.0); + } + return; case 0xd8: #ifdef _SCSI_DEBUG_LOG @@ -724,6 +741,9 @@ void SCSI_CDROM::start_command() case 0x00: /* Get first and last track numbers */ buffer->write(TO_BCD(1)); buffer->write(TO_BCD(track_num)); + // PC-8801 CD BIOS invites 4 bytes ? + buffer->write(0); + buffer->write(0); break; case 0x01: /* Get total disk size in MSF format */ { @@ -731,6 +751,8 @@ void SCSI_CDROM::start_command() buffer->write((msf >> 16) & 0xff); buffer->write((msf >> 8) & 0xff); buffer->write((msf >> 0) & 0xff); + // PC-8801 CD BIOS invites 4 bytes ? + buffer->write(0); } break; case 0x02: /* Get track information */ @@ -809,8 +831,9 @@ bool SCSI_CDROM::read_buffer(int length) } } while(length > 0) { - uint8_t tmp_buffer[SCSI_BUFFER_SIZE]; - int tmp_length = min(length, (int)sizeof(tmp_buffer)); + uint8_t tmp_buffer[2352]; +// int tmp_length = min(length, (int)sizeof(tmp_buffer)); + int tmp_length = 2352 - offset; if(fio_img->Fread(tmp_buffer, tmp_length, 1) != 1) { #ifdef _SCSI_DEBUG_LOG @@ -820,8 +843,8 @@ bool SCSI_CDROM::read_buffer(int length) set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND return false; } - for(int i = 0; i < tmp_length && length > 0; i++) { - if(offset >= 16 && offset < 16 + 2048) { + for(int i = 0; i < tmp_length; i++) { + if(offset >= 16 && offset < 16 + logical_block_size()) { int value = tmp_buffer[i]; buffer->write(value); length--; @@ -837,6 +860,28 @@ bool SCSI_CDROM::read_buffer(int length) return true; } +bool SCSI_CDROM::write_buffer(int length) +{ + for(int i = 0; i < length; i++) { + int value = buffer->read(); + if(command[0] == SCSI_CMD_MODE_SEL6) { + if(i == 4) { + #ifdef _SCSI_DEBUG_LOG + this->out_debug_log(_T("[SCSI_DEV:ID=%d] NEC Read Mode = %02X\n"), scsi_id, value); + #endif + read_mode = (value != 0); + } else if(i == 10) { + #ifdef _SCSI_DEBUG_LOG + this->out_debug_log(_T("[SCSI_DEV:ID=%d] NEC Retry Count = %02X\n"), scsi_id, value); + #endif + } + } + position++; + } + set_sense_code(SCSI_SENSE_NOSENSE); + return true; +} + int get_frames_from_msf(const char *string) { const char *ptr = string; diff --git a/source/src/vm/scsi_dev.cpp b/source/src/vm/scsi_dev.cpp index f7a8f521c..1db8e2da8 100644 --- a/source/src/vm/scsi_dev.cpp +++ b/source/src/vm/scsi_dev.cpp @@ -180,19 +180,20 @@ void SCSI_DEV::write_signal(int id, uint32_t data, uint32_t mask) switch(phase) { case SCSI_PHASE_DATA_OUT: if(--remain > 0) { + // flush buffer + if(buffer->full()) { + if(!write_buffer(buffer->count())) { + // change to status phase + set_dat(SCSI_STATUS_CHKCOND); + set_phase_delay(SCSI_PHASE_STATUS, 10.0); + break; + } + buffer->clear(); // just in case + } switch(command[0]) { case SCSI_CMD_WRITE6: case SCSI_CMD_WRITE10: case SCSI_CMD_WRITE12: - // flush buffer - if(buffer->full()) { - if(!write_buffer(buffer->count())) { - // change to status phase - set_dat(SCSI_STATUS_CHKCOND); - set_phase_delay(SCSI_PHASE_STATUS, 10.0); - break; - } - } // request to write next data { next_req_usec += 1000000.0 / bytes_per_sec; @@ -201,35 +202,20 @@ void SCSI_DEV::write_signal(int id, uint32_t data, uint32_t mask) } break; default: - // flush buffer - if(buffer->full()) { - buffer->clear(); - } // request to write next data set_req_delay(1, 1.0); break; } } else { - switch(command[0]) { - case SCSI_CMD_WRITE6: - case SCSI_CMD_WRITE10: - case SCSI_CMD_WRITE12: - // flush buffer - if(!buffer->empty()) { - if(!write_buffer(buffer->count())) { - // change to status phase - set_dat(SCSI_STATUS_CHKCOND); - set_phase_delay(SCSI_PHASE_STATUS, 10.0); - break; - } - } - break; - default: - // flush buffer - if(!buffer->empty()) { - buffer->clear(); + // flush buffer + if(!buffer->empty()) { + if(!write_buffer(buffer->count())) { + // change to status phase + set_dat(SCSI_STATUS_CHKCOND); + set_phase_delay(SCSI_PHASE_STATUS, 10.0); + break; } - break; + buffer->clear(); // just in case } // change to status phase set_dat(SCSI_STATUS_GOOD); @@ -451,7 +437,7 @@ void SCSI_DEV::set_msg(int value) void SCSI_DEV::set_req(int value) { #ifdef _SCSI_DEBUG_LOG - this->out_debug_log(_T("[SCSI_DEV:ID=%d] REQ = %d\n"), scsi_id, value ? 1 : 0); +// this->out_debug_log(_T("[SCSI_DEV:ID=%d] REQ = %d\n"), scsi_id, value ? 1 : 0); #endif if(event_req != -1) { cancel_event(this, event_req); @@ -521,25 +507,19 @@ void SCSI_DEV::start_command() position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]; position *= physical_block_size(); // transfer length - remain = 16; +// remain = 16; + remain = command[4]; // create sense data table buffer->clear(); - buffer->write(SCSI_SERROR_CURRENT); - buffer->write(0x00); - buffer->write(is_device_ready() ? SCSI_KEY_NOSENSE : SCSI_KEY_UNITATT); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x08); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); - buffer->write(0x00); + for(int i = 0; i < remain; i++) { + int value = 0; + switch(i) { + case 0: value = SCSI_SERROR_CURRENT; break; + case 2: value = is_device_ready() ? SCSI_KEY_NOSENSE : SCSI_KEY_UNITATT; break; + case 7: value = 0x08; break; + } + buffer->write(value); + } // change to data in phase set_dat(buffer->read()); set_phase_delay(SCSI_PHASE_DATA_IN, 10.0); diff --git a/source/src/vm/scsi_hdd.cpp b/source/src/vm/scsi_hdd.cpp index 09d254cda..faf03bd3d 100644 --- a/source/src/vm/scsi_hdd.cpp +++ b/source/src/vm/scsi_hdd.cpp @@ -123,6 +123,14 @@ uint32_t SCSI_HDD::max_logical_block_addr() 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())) { @@ -149,6 +157,14 @@ bool SCSI_HDD::read_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())) { diff --git a/source/src/vm/scsi_host.cpp b/source/src/vm/scsi_host.cpp index 8c6632d2a..82773a207 100644 --- a/source/src/vm/scsi_host.cpp +++ b/source/src/vm/scsi_host.cpp @@ -77,7 +77,7 @@ void SCSI_HOST::write_signal(int id, uint32_t data, uint32_t mask) case SIG_SCSI_ACK: #ifdef _SCSI_DEBUG_LOG - this->out_debug_log(_T("[SCSI_HOST] ACK = %d\n"), (data & mask) ? 1 : 0); +// this->out_debug_log(_T("[SCSI_HOST] ACK = %d\n"), (data & mask) ? 1 : 0); #endif write_signals(&outputs_ack, (data & mask) ? 0xffffffff : 0); ack_status = data & mask; -- 2.11.0