Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions devices/common/ata/atapicdrom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ int AtapiCdrom::device_postinit() {
parse_device_path(cdr_config, bus_id, dev_num);

auto bus_obj = dynamic_cast<IdeChannel*>(gMachineObj->get_comp_by_name(bus_id));
if (!bus_obj) {
LOG_F(ERROR, "%s: cdr_config device path %s does not specify a known IDE bus",
this->name.c_str(), cdr_config.c_str());
return -1;
}
bus_obj->register_device(dev_num, this);

std::string cdr_image_path = GET_STR_PROP("cdr_img");
Expand Down Expand Up @@ -100,6 +105,12 @@ void AtapiCdrom::perform_packet_command() {
switch (this->cmd_pkt[0]) {
case ScsiCommand::READ_CD:
{
// READ_CD currently bypasses the shared CD-ROM command dispatcher.
if (!this->ready_for_command()) {
this->present_status();
break;
}

lba = READ_DWORD_BE_U(&this->cmd_pkt[2]);
xfer_len = (this->cmd_pkt[6] << 16) | READ_WORD_BE_U(&this->cmd_pkt[7]);
if (this->cmd_pkt[9] == 0 && (this->cmd_pkt[10] & 7) == 0) {
Expand Down
5 changes: 5 additions & 0 deletions devices/common/scsi/scsiblockcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ void ScsiBlockCmds::init_block_device(uint8_t medium_type, uint8_t dev_flags,
}

void ScsiBlockCmds::process_command() {
if (!this->ready_for_command()) {
phy_impl->switch_phase(ScsiPhase::STATUS);
return;
}

int next_phase;

// use non-disk buffer by default
Expand Down
73 changes: 55 additions & 18 deletions devices/common/scsi/scsibus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.

#include <cinttypes>
#include <sstream>
#include <vector>

ScsiBus::ScsiBus(const std::string name)
{
Expand Down Expand Up @@ -338,29 +339,65 @@ void ScsiBus::attach_scsi_devices(const std::string bus_suffix)
}
}

int default_cdrom_id = -1;
std::string cdr_config = GET_STR_PROP("cdr_config");
if (!cdr_config.empty()) {
std::string bus_id;
uint32_t dev_num;
parse_device_path(cdr_config, bus_id, dev_num);
// Only consume SCSI paths; other buses handle their own CD-ROM configuration.
if (bus_id.starts_with("Scsi")) {
auto bus_obj = dynamic_cast<ScsiBus*>(gMachineObj->get_comp_by_name_optional(bus_id));
if (!bus_obj)
ABORT_F("cdr_config device path %s does not specify a known SCSI bus", cdr_config.c_str());
if (dev_num >= SCSI_MAX_DEVS)
ABORT_F("Invalid SCSI ID in cdr_config device path %s", cdr_config.c_str());
if (bus_obj == this) {
if (this->devices[dev_num])
ABORT_F("%s: cdr_config SCSI ID %u is already occupied", bus_id.c_str(), dev_num);
default_cdrom_id = dev_num;
}
}
}

image_path = GET_STR_PROP("cdr_img" + bus_suffix);
std::vector<std::string> cdrom_paths;
if (!image_path.empty()) {
std::istringstream image_stream(image_path);
while (std::getline(image_stream, path, ':')) {
// do two passes because we start at ID 3.
// Keep empty entries, including the last one, as empty CD-ROM drives.
size_t start = 0;
size_t end;
do {
end = image_path.find(':', start);
cdrom_paths.push_back(image_path.substr(start, end - start));
start = end + 1;
} while (end != std::string::npos);
} else if (default_cdrom_id >= 0) {
cdrom_paths.push_back("");
}
for (const auto& path : cdrom_paths) {
if (default_cdrom_id >= 0) {
scsi_id = default_cdrom_id;
default_cdrom_id = -1;
} else {
// do two passes because we start at ID 3.
for (scsi_id = 3; scsi_id < SCSI_MAX_DEVS * 2 &&
this->devices[scsi_id % SCSI_MAX_DEVS]; scsi_id++) {}
}

if (scsi_id < SCSI_MAX_DEVS * 2) {
scsi_id = scsi_id % SCSI_MAX_DEVS;
std::string scsi_device_name = "ScsiCdrom" + bus_suffix + "," +
std::to_string(scsi_id);
ScsiCdrom *scsi_device = new ScsiCdrom(scsi_device_name, scsi_id);
gMachineObj->add_device(scsi_device_name,
std::unique_ptr<ScsiCdrom>(scsi_device));
this->register_device(scsi_id, scsi_device);
if (!scsi_device->insert_image(path))
ABORT_F("Could not insert CD-ROM image, %s", path.c_str());
}
else {
LOG_F(ERROR, "%s: Too many devices. CD-ROM \"%s\" was not added.",
this->get_name().c_str(), path.c_str());
}
if (scsi_id < SCSI_MAX_DEVS * 2) {
scsi_id = scsi_id % SCSI_MAX_DEVS;
std::string scsi_device_name = "ScsiCdrom" + bus_suffix + "," +
std::to_string(scsi_id);
ScsiCdrom *scsi_device = new ScsiCdrom(scsi_device_name, scsi_id);
gMachineObj->add_device(scsi_device_name,
std::unique_ptr<ScsiCdrom>(scsi_device));
this->register_device(scsi_id, scsi_device);
if (!path.empty() && !scsi_device->insert_image(path))
ABORT_F("Could not insert CD-ROM image, %s", path.c_str());
}
else {
LOG_F(ERROR, "%s: Too many devices. CD-ROM \"%s\" was not added.",
this->get_name().c_str(), path.c_str());
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions devices/common/scsi/scsicdromcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ ScsiCdromCmds::ScsiCdromCmds() {
}

void ScsiCdromCmds::process_command() {
if (!this->ready_for_command()) {
phy_impl->switch_phase(ScsiPhase::STATUS);
return;
}

int next_phase;

// use non-disk buffer by default
Expand Down
21 changes: 19 additions & 2 deletions devices/common/scsi/scsicommoncmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,33 @@ int ScsiCommonCmds::verify_cdb() {
}

int ScsiCommonCmds::test_unit_ready() {
// Assume that LUN is okay and the status has been set to GOOD
this->ready_for_command(true);
return ScsiPhase::STATUS;
}

bool ScsiCommonCmds::ready_for_command(bool force_check) {
// TUR forces a check from its handler; dispatch lets it and media-independent
// commands through to ScsiCommonCmds.
if (!force_check) {
switch (this->cdb_ptr[0]) {
case ScsiCommand::INQUIRY:
case ScsiCommand::REQ_SENSE:
case ScsiCommand::TEST_UNIT_READY:
case ScsiCommand::MODE_SENSE_6:
case ScsiCommand::MODE_SENSE_10:
return true;
}
}

if (!phy_impl->is_device_ready()) {
this->sense_key = ScsiSense::NOT_READY;
this->asc = phy_impl->not_ready_reason();
this->ascq = 0;
phy_impl->set_status(ScsiStatus::CHECK_CONDITION, this->sense_key);
return false;
}

return ScsiPhase::STATUS;
return true;
}

int ScsiCommonCmds::inquiry() {
Expand Down
2 changes: 2 additions & 0 deletions devices/common/scsi/scsicommoncmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class ScsiCommonCmds {
virtual void invalid_command();
virtual void illegal_request(uint8_t asc, uint8_t ascq, bool is_cdb = true);

bool ready_for_command(bool force_check = false);

int get_one_page(uint8_t ctrl, uint8_t page, uint8_t subpage, uint8_t* out_ptr,
int avail_len);

Expand Down
2 changes: 2 additions & 0 deletions machines/machinealchemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ static const PropMap pm6400_settings = {
new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32}))},
{"hdd_config",
new StrProperty("Ide0:0")},
{"cdr_config",
new StrProperty("ScsiMesh:3")},
{"emmo",
new BinProperty(0)},
};
Expand Down
2 changes: 2 additions & 0 deletions machines/machinecatalyst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ static const PropMap pm7200_settings = {
new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
{"rambank4_size",
new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))},
{"cdr_config",
new StrProperty("ScsiCurio:3")},
{"emmo",
new BinProperty(0)},
{"cpu",
Expand Down
2 changes: 2 additions & 0 deletions machines/machinegazelle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ static const PropMap pm6500_settings = {
new IntProperty(32, std::vector<uint32_t>({ 4, 8, 16, 32, 64}))},
{"rambank2_size",
new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64}))},
{"cdr_config",
new StrProperty("ScsiMesh:3")},
{"emmo",
new BinProperty(0)},
{"hdd_config",
Expand Down
2 changes: 2 additions & 0 deletions machines/machinepdm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ static const PropMap pm6100_settings = {
new StrProperty("HiRes12-14in", PDMBuiltinMonitorIDs)},
{"pds",
new StrProperty("")},
{"cdr_config",
new StrProperty("ScsiCurio:3")},
{"emmo",
new BinProperty(0)},
};
Expand Down
2 changes: 2 additions & 0 deletions machines/machinepippin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ static const PropMap Pippin_settings = {
new IntProperty(0, std::vector<uint32_t>({0, 1, 4, 8, 16}))},
{"rambank4_size",
new IntProperty(0, std::vector<uint32_t>({0, 1, 4, 8, 16}))},
{"cdr_config",
new StrProperty("ScsiCurio:3")},
{"emmo",
new BinProperty(0)},
{"adb_devices",
Expand Down
16 changes: 9 additions & 7 deletions machines/machineproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <loguru.hpp>

#include <algorithm>
#include <cerrno>
#include <cinttypes>
#include <string>
#include <sstream>
Expand Down Expand Up @@ -151,15 +152,16 @@ void parse_device_path(std::string dev_path, std::string& bus_id, uint32_t& dev_
dev_num = -1;

size_t delimiter_pos = dev_path.find(":");
if (delimiter_pos == std::string::npos)
if (delimiter_pos == std::string::npos || delimiter_pos == 0)
ABORT_F("Invalid device path %s", dev_path.c_str());

bus_id = dev_path.substr(0, delimiter_pos);

try {
dev_num = (uint32_t)strtoul(dev_path.substr(delimiter_pos+1).c_str(), 0, 0);
} catch (std::string bad_string) {
ABORT_F("Invalid device number %s in device path %s", bad_string.c_str(),
dev_path.c_str());
}
std::string number = dev_path.substr(delimiter_pos + 1);
char* end;
errno = 0;
unsigned long value = strtoul(number.c_str(), &end, 0);
if (end == number.c_str() || *end || errno == ERANGE || value > UINT32_MAX)
ABORT_F("Invalid device number %s in device path %s", number.c_str(), dev_path.c_str());
dev_num = (uint32_t)value;
}
1 change: 1 addition & 0 deletions machines/machinetnt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ static const PropMap pm7500_settings_ ## cpu = { \
{"rambank10_size", new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))}, \
{"rambank11_size", new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))}, \
{"rambank12_size", new IntProperty( 0, std::vector<uint32_t>({0, 4, 8, 16, 32, 64, 128}))}, \
{"cdr_config", new StrProperty("ScsiCurio:3")}, \
{"emmo", new BinProperty(0)}, \
{"cpu", new StrProperty(# cpu, std::vector<std::string>({"601", "604", "604e", "750"}))}, \
};
Expand Down
Loading