scsiphysdevice: implement writing of big data in chunks.

This commit is contained in:
Maxim Poliakovski
2026-03-10 00:20:45 +01:00
parent f2a9f3cb56
commit 202446025a
4 changed files with 61 additions and 11 deletions
+20 -1
View File
@@ -41,7 +41,7 @@ void ScsiBlockCmds::init_block_device(uint8_t medium_type, uint8_t dev_flags) {
this->device_flags = dev_flags;
phy_impl->set_read_more_data_cb(
[this](int* dsize, uint8_t** dptr) {
[this](int* dsize, uint8_t** dptr) -> bool {
if (this->remain_size) {
*dsize = this->read_more();
*dptr = (uint8_t *)this->data_cache.get();
@@ -50,6 +50,25 @@ void ScsiBlockCmds::init_block_device(uint8_t medium_type, uint8_t dev_flags) {
return false;
}
);
if (this->is_writeable) {
phy_impl->set_write_more_data_cb(
[this](int* dsize, uint8_t** dptr) -> bool {
if (this->remain_size) {
*dsize = this->write_more();
*dptr = (uint8_t *)this->data_cache.get();
return true;
} else
return false;
}
);
} else {
phy_impl->set_write_more_data_cb(
[this](int* dsize, uint8_t** dptr) {
return false;
}
);
}
}
void ScsiBlockCmds::process_command() {
+7 -4
View File
@@ -60,6 +60,12 @@ ScsiCdrom::ScsiCdrom(std::string name, int my_id) :
}
);
this->set_write_more_data_cb(
[this](int* dsize, uint8_t** dptr) {
return false;
}
);
// populate device info for INQUIRY
this->dev_type = ScsiDevType::CD_ROM;
this->is_removable = true; // removable medium
@@ -80,11 +86,8 @@ void ScsiCdrom::process_command()
return;
}
this->pre_xfer_action = nullptr;
this->post_xfer_action = nullptr;
// assume successful command execution
this->status = ScsiStatus::GOOD;
phy_impl->set_status(ScsiStatus::GOOD);
this->msg_buf[0] = ScsiMessage::COMMAND_COMPLETE;
// use internal data buffer by default
+2 -2
View File
@@ -39,8 +39,6 @@ ScsiHardDisk::ScsiHardDisk(std::string name, int my_id) : ScsiPhysDevice(name, m
this->set_buf_ptr(this->data_buf);
this->set_buffer(this->data_buf);
this->init_block_device(0, 0);
// populate device info for INQUIRY
this->dev_type = ScsiDevType::DIRECT_ACCESS; // direct access device (hard drive)
this->is_removable = false; // non-removable medium
@@ -64,6 +62,8 @@ void ScsiHardDisk::insert_image(std::string filename) {
ABORT_F("%s: image file too large", this->name.c_str());
this->is_writeable = true;
this->init_block_device(0, 0);
}
void ScsiHardDisk::process_command() {
+32 -4
View File
@@ -235,10 +235,38 @@ int ScsiPhysDevice::send_data(uint8_t* dst_ptr, const int count)
int ScsiPhysDevice::rcv_data(const uint8_t* src_ptr, const int count)
{
// accumulating incoming data in the pre-configured buffer
std::memcpy(this->data_ptr, src_ptr, count);
this->data_ptr += count;
this->data_size += count;
if (src_ptr == nullptr || !count)
return 0;
// DATA_OUT can transfer big data in several chunks while crossing buffer boundaries
if (this->cur_phase == ScsiPhase::DATA_OUT) {
int remainder = count;
while (remainder) {
if (this->data_size < this->incoming_size) {
int chunk_size = std::min(this->incoming_size - this->data_size, remainder);
if (chunk_size) {
std::memcpy(this->data_ptr, src_ptr, chunk_size);
src_ptr += chunk_size;
this->data_ptr += chunk_size;
this->data_size += chunk_size;
remainder -= chunk_size;
}
}
if (this->data_size >= this->incoming_size) {
if (!this->write_more_data(&this->incoming_size, &this->data_ptr))
break;
this->data_size = 0;
}
}
return count - remainder;
} else {
// accumulating incoming data in the pre-configured buffer
std::memcpy(this->data_ptr, src_ptr, count);
this->data_ptr += count;
this->data_size += count;
}
if (this->cur_phase == ScsiPhase::COMMAND)
this->next_step();