From 3f826b8971b0e1be33ae720dd88f95a0e4da0d68 Mon Sep 17 00:00:00 2001 From: joevt Date: Sat, 9 Mar 2024 21:44:12 -0800 Subject: [PATCH] scsi: Add illegal_command method. - scsicdrom now logs unsupported commands instead of abort. --- devices/common/scsi/scsi.h | 1 + devices/common/scsi/scsicdrom.cpp | 79 ++++++++++++++++++++++++++---- devices/common/scsi/scsidevice.cpp | 12 +++++ devices/common/scsi/scsihd.cpp | 43 +++++++++++++++- 4 files changed, 125 insertions(+), 10 deletions(-) diff --git a/devices/common/scsi/scsi.h b/devices/common/scsi/scsi.h index fe47b4e..4582758 100644 --- a/devices/common/scsi/scsi.h +++ b/devices/common/scsi/scsi.h @@ -189,6 +189,7 @@ public: virtual int send_data(uint8_t* dst_ptr, int count); virtual int rcv_data(const uint8_t* src_ptr, const int count); virtual bool check_lun(); + void illegal_command(const uint8_t* cmd); virtual bool prepare_data() = 0; virtual bool get_more_data() = 0; diff --git a/devices/common/scsi/scsicdrom.cpp b/devices/common/scsi/scsicdrom.cpp index cfac57d..a7cff07 100644 --- a/devices/common/scsi/scsicdrom.cpp +++ b/devices/common/scsi/scsicdrom.cpp @@ -56,44 +56,105 @@ void ScsiCdrom::process_command() // use internal data buffer by default this->data_ptr = this->data_buf; - switch (cmd_buf[0]) { + uint8_t* cmd = this->cmd_buf; + + switch (cmd[0]) { case ScsiCommand::TEST_UNIT_READY: this->switch_phase(ScsiPhase::STATUS); break; + case ScsiCommand::REWIND: + this->illegal_command(cmd); + break; + case ScsiCommand::REQ_SENSE: + this->illegal_command(cmd); + break; + case ScsiCommand::FORMAT_UNIT: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_BLK_LIMITS: + this->illegal_command(cmd); + break; case ScsiCommand::READ_6: - lba = ((cmd_buf[1] & 0x1F) << 16) + (cmd_buf[2] << 8) + cmd_buf[3]; - this->read(lba, cmd_buf[4], 6); + lba = ((cmd[1] & 0x1F) << 16) + (cmd[2] << 8) + cmd[3]; + this->read(lba, cmd[4], 6); + break; + case ScsiCommand::WRITE_6: + this->illegal_command(cmd); + break; + case ScsiCommand::SEEK_6: + this->illegal_command(cmd); break; case ScsiCommand::INQUIRY: this->inquiry(); break; + case ScsiCommand::VERIFY_6: + this->illegal_command(cmd); + break; case ScsiCommand::MODE_SELECT_6: - this->incoming_size = this->cmd_buf[4]; + this->incoming_size = cmd[4]; this->switch_phase(ScsiPhase::DATA_OUT); break; + case ScsiCommand::RELEASE_UNIT: + this->illegal_command(cmd); + break; + case ScsiCommand::ERASE_6: + this->illegal_command(cmd); + break; case ScsiCommand::MODE_SENSE_6: this->mode_sense(); break; + case ScsiCommand::START_STOP_UNIT: + this->illegal_command(cmd); + break; + case ScsiCommand::DIAG_RESULTS: + this->illegal_command(cmd); + break; + case ScsiCommand::SEND_DIAGS: + this->illegal_command(cmd); + break; case ScsiCommand::PREVENT_ALLOW_MEDIUM_REMOVAL: - this->eject_allowed = (this->cmd_buf[4] & 1) == 0; + this->eject_allowed = (cmd[4] & 1) == 0; this->switch_phase(ScsiPhase::STATUS); break; case ScsiCommand::READ_CAPACITY_10: this->read_capacity(); break; case ScsiCommand::READ_10: - lba = READ_DWORD_BE_U(&this->cmd_buf[2]); - xfer_len = READ_WORD_BE_U(&this->cmd_buf[7]); - if (this->cmd_buf[1] & 1) { + lba = READ_DWORD_BE_U(&cmd[2]); + xfer_len = READ_WORD_BE_U(&cmd[7]); + if (cmd[1] & 1) { ABORT_F("%s: RelAdr bit set in READ_10", this->name.c_str()); } read(lba, xfer_len, 10); break; + case ScsiCommand::WRITE_10: + this->illegal_command(cmd); + break; + case ScsiCommand::VERIFY_10: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_LONG_10: + this->illegal_command(cmd); + break; + case ScsiCommand::MODE_SENSE_10: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_12: + this->illegal_command(cmd); + break; + + // CD-ROM specific commands case ScsiCommand::READ_TOC: this->read_toc(); break; + case ScsiCommand::SET_CD_SPEED: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_CD: + this->illegal_command(cmd); + break; default: - ABORT_F("%s: unsupported command %d", this->name.c_str(), this->cmd_buf[0]); + this->illegal_command(cmd); } } diff --git a/devices/common/scsi/scsidevice.cpp b/devices/common/scsi/scsidevice.cpp index 4c62e5f..b7c95d9 100644 --- a/devices/common/scsi/scsidevice.cpp +++ b/devices/common/scsi/scsidevice.cpp @@ -236,3 +236,15 @@ bool ScsiDevice::check_lun() } return true; } + +void ScsiDevice::illegal_command(const uint8_t *cmd) +{ + LOG_F(ERROR, "%s: unsupported command: 0x%02x", this->name.c_str(), cmd[0]); + this->status = ScsiStatus::CHECK_CONDITION; + this->sense = ScsiSense::ILLEGAL_REQ; + this->asc = 0x20; // Invalid command operation code + this->ascq = 0; + this->sksv = 0xc0; // sksv=1, C/D=Command, BPV=0, BP=0 + this->field = 0; + this->switch_phase(ScsiPhase::STATUS); +} diff --git a/devices/common/scsi/scsihd.cpp b/devices/common/scsi/scsihd.cpp index 5df685e..ef2ec32 100644 --- a/devices/common/scsi/scsihd.cpp +++ b/devices/common/scsi/scsihd.cpp @@ -87,6 +87,9 @@ void ScsiHardDisk::process_command() { case ScsiCommand::INQUIRY: this->inquiry(); break; + case ScsiCommand::READ_BLK_LIMITS: + this->illegal_command(cmd); + break; case ScsiCommand::READ_6: lba = ((cmd[1] & 0x1F) << 16) + (cmd[2] << 8) + cmd[3]; transfer_len = cmd[4]; @@ -112,20 +115,58 @@ void ScsiHardDisk::process_command() { lba = ((cmd[1] & 0x1F) << 16) + (cmd[2] << 8) + cmd[3]; seek(lba); break; + case ScsiCommand::VERIFY_6: + this->illegal_command(cmd); + break; case ScsiCommand::MODE_SELECT_6: mode_select_6(cmd[4]); break; + case ScsiCommand::RELEASE_UNIT: + this->illegal_command(cmd); + break; + case ScsiCommand::ERASE_6: + this->illegal_command(cmd); + break; case ScsiCommand::MODE_SENSE_6: this->mode_sense_6(); break; + case ScsiCommand::START_STOP_UNIT: + this->illegal_command(cmd); + break; + case ScsiCommand::DIAG_RESULTS: + this->illegal_command(cmd); + break; + case ScsiCommand::SEND_DIAGS: + this->illegal_command(cmd); + break; case ScsiCommand::READ_CAPACITY_10: this->read_capacity_10(); break; + case ScsiCommand::VERIFY_10: + this->illegal_command(cmd); + break; case ScsiCommand::READ_BUFFER: read_buffer(); break; + case ScsiCommand::MODE_SENSE_10: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_12: + this->illegal_command(cmd); + break; + + // CD-ROM specific commands + case ScsiCommand::READ_TOC: + this->illegal_command(cmd); + break; + case ScsiCommand::SET_CD_SPEED: + this->illegal_command(cmd); + break; + case ScsiCommand::READ_CD: + this->illegal_command(cmd); + break; default: - LOG_F(WARNING, "%s: unrecognized command: %x", this->name.c_str(), cmd[0]); + this->illegal_command(cmd); } }