diff --git a/devices/common/scsi/scsi.h b/devices/common/scsi/scsi.h index 5c92952..f05794d 100644 --- a/devices/common/scsi/scsi.h +++ b/devices/common/scsi/scsi.h @@ -89,7 +89,7 @@ enum ScsiCommand : uint8_t { TEST_UNIT_READY = 0x00, REWIND = 0x01, REQ_SENSE = 0x03, - FORMAT = 0x04, + FORMAT_UNIT = 0x04, READ_BLK_LIMITS = 0x05, READ_6 = 0x08, WRITE_6 = 0x0A, diff --git a/devices/common/scsi/scsihd.cpp b/devices/common/scsi/scsihd.cpp index 197baa1..3e81e5a 100644 --- a/devices/common/scsi/scsihd.cpp +++ b/devices/common/scsi/scsihd.cpp @@ -21,6 +21,7 @@ along with this program. If not, see . /** @file Generic SCSI Hard Disk emulation. */ +#include #include #include #include @@ -43,7 +44,7 @@ void ScsiHardDisk::insert_image(std::string filename) { //We don't want to store everything in memory, but //we want to keep the hard disk available. if (!this->hdd_img.open(filename)) - ABORT_F("SCSI-HD: could not determine file size using stat()"); + ABORT_F("SCSI-HD: could not open image file %s", filename.c_str()); this->img_size = this->hdd_img.size(); this->total_blocks = (this->img_size + HDD_SECTOR_SIZE - 1) / HDD_SECTOR_SIZE; @@ -53,7 +54,6 @@ void ScsiHardDisk::process_command() { uint32_t lba = 0; uint16_t transfer_len = 0; uint16_t alloc_len = 0; - uint8_t param_len = 0; uint8_t page_code = 0; uint8_t subpage_code = 0; @@ -78,6 +78,9 @@ void ScsiHardDisk::process_command() { alloc_len = cmd[4]; req_sense(alloc_len); break; + case ScsiCommand::FORMAT_UNIT: + this->format(); + break; case ScsiCommand::INQUIRY: this->inquiry(); break; @@ -107,8 +110,7 @@ void ScsiHardDisk::process_command() { seek(lba); break; case ScsiCommand::MODE_SELECT_6: - param_len = cmd[4]; - mode_select_6(param_len); + mode_select_6(cmd[4]); break; case ScsiCommand::MODE_SENSE_6: this->mode_sense_6(); @@ -200,14 +202,21 @@ int ScsiHardDisk::send_diagnostic() { return 0x0; } -int ScsiHardDisk::mode_select_6(uint8_t param_len) { - if (param_len == 0) { - return 0x0; - } - else { - LOG_F(WARNING, "Mode Select calling for param length of: %d", param_len); - return param_len; +void ScsiHardDisk::mode_select_6(uint8_t param_len) { + if (!param_len) { + this->switch_phase(ScsiPhase::STATUS); + return; } + + this->incoming_size = param_len; + + std::memset(&this->img_buffer[0], 0xDD, HDD_SECTOR_SIZE); + + this->post_xfer_action = [this]() { + // TODO: parse the received mode parameter list here + }; + + this->switch_phase(ScsiPhase::DATA_OUT); } static char Apple_Copyright_Page_Data[] = "APPLE COMPUTER, INC "; @@ -234,6 +243,10 @@ void ScsiHardDisk::mode_sense_6() { this->img_buffer[12] = page_code; switch(page_code) { + case 1: // read-write error recovery page + this->img_buffer[13] = 6; // data size - 1 + std::memset(&this->img_buffer[14], 0, 6); + break; case 3: // Format device page this->img_buffer[13] = 22; // data size - 1 std::memset(&this->img_buffer[14], 0, 22); @@ -291,6 +304,14 @@ void ScsiHardDisk::read_capacity_10() { void ScsiHardDisk::format() { + LOG_F(WARNING, "SCSI-HD: attempt to format the disk!"); + + if (this->cmd_buf[1] & 0x10) + ABORT_F("SCSI-HD: defect list isn't supported yet"); + + TimerManager::get_instance()->add_oneshot_timer(NS_PER_SEC, [this]() { + this->switch_phase(ScsiPhase::STATUS); + }); } void ScsiHardDisk::read(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) { diff --git a/devices/common/scsi/scsihd.h b/devices/common/scsi/scsihd.h index 973e74d..df05ed3 100644 --- a/devices/common/scsi/scsihd.h +++ b/devices/common/scsi/scsihd.h @@ -45,10 +45,10 @@ public: bool prepare_data(); protected: - int test_unit_ready(); - int req_sense(uint16_t alloc_len); - int send_diagnostic(); - int mode_select_6(uint8_t param_len); + int test_unit_ready(); + int req_sense(uint16_t alloc_len); + int send_diagnostic(); + void mode_select_6(uint8_t param_len); void mode_sense_6(); void format(); @@ -69,9 +69,9 @@ private: char img_buffer[1 << 21]; // TODO: add proper buffer management! - uint32_t cur_buf_cnt = 0; - uint8_t error = ScsiError::NO_ERROR; - uint8_t msg_code = 0; + uint32_t cur_buf_cnt = 0; + uint8_t error = ScsiError::NO_ERROR; + uint8_t msg_code = 0; //inquiry info char vendor_info[8] = {'D', 'i', 'n', 'g', 'u', 's', 'D', '\0'};