mirror of
https://github.com/dingusdev/dingusppc.git
synced 2026-04-20 18:17:02 +00:00
scsiphysdevice: implement writing of big data in chunks.
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user